我已經通過編譯一個groovy屬性類來與GWT Autobeans模型進行互操作,構建了一個原始接口Shim生成器。這是目前避開ASM/cglib學習曲線的非常粗略的方法。背景:對於Autobeans,您只能使用接口,並且對於我嘗試過的所有訪問嘗試,sun。*代理不能使用gson interop。但是,當Groovy類加載器是GsonBuilder本地時,事情變得更容易一些。請注意,除非gsonBuilder註冊實際上是從groovy本身調用的,否則這將失敗。
訪問墊片工廠創建一個作爲一個單名JSON_SHIM和呼叫
JSON_SHIM.getShim( 「{}」,MyInterface.class)
如果需要註冊並創建一個[空白]實例。如果您的界面中有界面,您必須預先註冊這些界面,以免超出使用範圍。這只是足夠的神奇使用平板 Autobeans與GSON,而不是一個完整的框架。 這個生成器中沒有groovy代碼,所以有javassist-foo的人可以重複這個實驗。
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;
}
}
嗨布魯斯,所以我想我抓到了什麼是什麼,看起來像GSON只是不支持多態反序列化。我在你的網站上看到你有一些傑克遜的例子(包括多態性)。你會推薦在這個時候使用傑克遜而不是gson嗎?謝謝 – user291701
是的,我建議在Gson上使用Jackson,如http://programmerbruce.blogspot.com/2011/07/gson-v-jackson-part-6.html中所述。傑克遜擁有體面的內置支持多態性,以及其他優勢,如顯着更好的性能。對於感興趣的,關於Jackson的多態反序列化的帖子在http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html –