Ho creato un generatore di shim di interfaccia primitivo compilando una classe di proprietà groovy per interoperare con un modello Autobeans GWT. questo è un metodo veramente approssimativo per aggirare la curva di apprendimento ASM/cglib per ora. background su questo: con Autobeans, puoi usare solo le interfacce, e il sole. * i proxy non sono in grado di interoperare con GSON per tutti i tentativi di accesso che ho sperimentato. MA, quando groove classloader è locale a GsonBuilder, le cose diventano un po 'più semplici. nota, questo fallisce a meno che la registrazione di gsonBuilder non sia effettivamente chiamata all'interno dello stesso groovy.
per accedere alla fabbrica di spessore creare uno come nomi Singleton JSON_SHIM e chiamare
JSON_SHIM.getShim ("{}", MyInterface.class)
di registrare, se necessario, e creare un [blank] istanza. se hai interfacce nelle tue interfacce, devi pre-registrarle troppo prima dell'uso. questa è solo una magia sufficiente per usare flat Autobeans con gson, non un intero framework. non c'è alcun codice groovy in questo generatore, quindi qualcuno con javassist-foo può ripetere l'esperimento.
import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
import groovy.lang.GroovyClassLoader;
import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
public class GroovyGsonShimFactory {
private Map<Class, Method> shimMethods = new LinkedHashMap<>();
private void generateGroovyProxy(Class ifaceClass) {
String shimClassName = ifaceClass.getSimpleName() + "$Proxy";
String ifaceClassCanonicalName = ifaceClass.getCanonicalName();
String s = "import com.google.gson.*;\n" +
"import org.apache.commons.beanutils.BeanUtils;\n" +
"import java.lang.reflect.*;\n" +
"import java.util.*;\n\n" +
"public class "+shimClassName+" implements "+ifaceClassCanonicalName+" {\n" ;
{
PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(ifaceClass);
for (PropertyDescriptor p : propertyDescriptors) {
String name = p.getName();
String tname = p.getPropertyType().getCanonicalName();
s += "public " + tname + " " + name + ";\n";
s += " " + p.getReadMethod().toGenericString().replace("abstract", "").replace(ifaceClassCanonicalName + ".", "") + "{return " + name + ";};\n";
Method writeMethod = p.getWriteMethod();
if (writeMethod != null)
s += " " + writeMethod.toGenericString().replace("abstract", "").replace(ifaceClassCanonicalName + ".", "").replace(")", " v){" + name + "=v;};") + "\n\n";
}
}
s+= " public static "+ifaceClassCanonicalName+" fromJson(String s) {\n" +
" return (" +ifaceClassCanonicalName+
")cydesign.strombolian.server.ddl.DefaultDriver.gson().fromJson(s, "+shimClassName+".class);\n" +
" }\n" +
" static public interface foo extends InstanceCreator<"+ifaceClassCanonicalName+">, JsonSerializer<"+ifaceClassCanonicalName+">, JsonDeserializer<"+ifaceClassCanonicalName+"> {}\n" +
" static {\n" +
" cydesign.strombolian.server.ddl.DefaultDriver.builder().registerTypeAdapter("+ifaceClassCanonicalName+".class, new foo() {\n" +
" public "+ifaceClassCanonicalName+" deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {\n" +
" return context.deserialize(json, "+shimClassName+".class);\n" +
" }\n" +
"\n" +
" public "+ifaceClassCanonicalName+" createInstance(java.lang.reflect.Type type) {\n" +
" try {\n" +
" return new "+shimClassName+"();\n" +
" } catch (Exception e) {\n" +
" e.printStackTrace(); \n" +
" }\n" +
" return null;\n" +
" }\n" +
"\n" +
" @Override\n" +
" public JsonElement serialize("+ifaceClassCanonicalName+" src, Type typeOfSrc, JsonSerializationContext context) {\n" +
" LinkedHashMap linkedHashMap = new LinkedHashMap();\n" +
" try {\n" +
" BeanUtils.populate(src, linkedHashMap);\n" +
" return context.serialize(linkedHashMap);\n" +
" } catch (Exception e) {\n" +
" e.printStackTrace(); \n" +
" }\n" +
"\n" +
" return null;\n" +
" }\n" +
" });\n" +
" }\n\n" +
"};";
System.err.println("" + s);
ClassLoader parent = DefaultDriver.class.getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
final Class gClass = loader.parseClass(s);
try {
Method shimMethod = gClass.getMethod("fromJson", String.class);
shimMethods.put(ifaceClass, shimMethod);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public <T> T getShim(String json, Class<T> ifaceClass) {
if (!shimMethods.containsKey(ifaceClass))
generateGroovyProxy(ifaceClass);
T shim = null;//= gson().shimMethods(json, CowSchema.class);
try {
shim = (T) shimMethods.get(ifaceClass).invoke(null, json);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return shim;
}
}
Ciao Bruce, quindi penso di essere coinvolto in quello che è, sembra che Gson non supporti ancora la deserializzazione polimorfica. Ho visto sul tuo sito che hai alcuni esempi di jackson (che includono il polimorfismo). Consiglieresti di usare jackson over gson a questo punto? Grazie – user291701
Sì, mi consiglia di utilizzare Jackson su Gson, come delineato in http://programmerbruce.blogspot.com/2011/07/gson-v-jackson-part-6.html. Jackson ha un supporto integrato decente per il polimorfismo, oltre ad altri vantaggi, come prestazioni significativamente migliori. Per gli interessati, il post sulla deserializzazione polimorfica con Jackson è disponibile all'indirizzo http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html –