Tôi đã tạo một trình tạo shim giao diện nguyên thủy bằng cách biên dịch một lớp thuộc tính groovy để tương thích với mô hình GWT Autobeans. đây là một phương pháp thực sự thô bạo để bỏ qua đường cong học tập ASM/cglib hiện tại. nền tảng về điều này: với Autobeans, bạn chỉ có thể sử dụng giao diện và mặt trời. * proxy không có khả năng tương tác gson cho mọi nỗ lực truy cập mà tôi đã thử nghiệm. NHƯNG, khi trình nạp lớp groovy là cục bộ cho GsonBuilder, mọi thứ trở nên dễ dàng hơn một chút. lưu ý, điều này không thành công trừ khi đăng ký gsonBuilder thực sự được gọi từ bên trong bản thân groovy.
để truy cập máy shim tạo như một tên singleton JSON_SHIM và gọi
JSON_SHIM.getShim ("{}", MyInterface.class)
đăng ký nếu cần thiết và tạo ra một [trống] dụ. nếu bạn có giao diện trong giao diện của mình, bạn phải đăng ký trước những giao diện quá trước khi sử dụng. đây chỉ là đủ ma thuật để sử dụng phẳng Tự động với gson, không phải toàn bộ khuôn khổ. không có mã groovy trong trình tạo này, vì vậy ai đó có javassist-foo có thể lặp lại thử nghiệm.
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;
}
}
Xin chào Bruce, vì vậy tôi nghĩ rằng tôi bị cuốn theo những gì, có vẻ như gson không hỗ trợ deserialization đa hình. Tôi đã nhìn thấy trên trang web của bạn rằng bạn có một số ví dụ jackson (trong đó bao gồm đa hình). Bạn có khuyên bạn nên sử dụng jackson trên gson vào thời điểm này? Cảm ơn – user291701
Có, tôi khuyên bạn nên sử dụng Jackson trên Gson, như được nêu trong http://programmerbruce.blogspot.com/2011/07/gson-v-jackson-part-6.html. Jackson có hỗ trợ tích hợp sẵn cho tính đa hình, cũng như các ưu điểm khác, chẳng hạn như hiệu năng tốt hơn đáng kể. Đối với những người quan tâm, bài đăng trên deserialization đa hình với Jackson là tại http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html –