来自Json的Gson反编译generics
在使用Android应用程序时,我遇到了一个问题,当我想制作一个终极通用方法来发送HTTP请求(使用loopj)并反序列化它们(使用Gson)。
正如您在使用gson.fromJson
可能知道的gson.fromJson
您不能这样做:
gson.fromJson(responseBody, new TypeToken() {}.getType());
要么
gson.fromJson(responseBody, new TypeToken<ArrayList>() {}.getType())
您已经作为T
传递的实际对象(或LinkedTreeMap
情况下的实际对象列表)代替了LinkedTreeMap
对象(或LinkedTreeMap
对象列表)。
如果您仍想要反序列化generics类型对象(-s),请参阅下面的答案。
+ Bonus:loopj + gson的终极通用解决方案
感谢这些post的作者和评论者:
http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/
如何获得通用接口的具体类型
Java Type Generic作为GSON的参数
将JSON对象反序列化为generics类型java对象
首先,我们需要获得generics类型T
的实际类。
我们可以通过传递类本身( Class
)或从具有generics类型的对象( SomeObject
)获取类来实现。 我将在示例中使用第二种情况。
然后我们需要创建一个Element
类的特殊对象,它将告诉Gson用于反序列化的类。
public T getObject(String json, SomeObject someObjectWithGenericType) { Class cl = getTypeClassOfObject(someObjWithGenericType); T object = gson.fromJson(json, new Element (cl)); return object; } private Class getTypeClassOfObject(Object obj) { return (Class) ((ParameterizedType) obj.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } private class Element implements ParameterizedType { private Class cl; public Element(Class cl) { this.cl = cl; } public Type[] getActualTypeArguments() { return new Type[] {cl}; } public Type getRawType() { return cl; } public Type getOwnerType() { return null; } }
如果您的SomeObject
是一个接口(可能是回调,稍后您将在loopj示例中看到),您可以使用此方法而不是getTypeClassOfObject
:
private Class getTypeClassOfInterfaceObject(Object obj) { return (Class) ((ParameterizedType) obj.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0]; }
将JSON数组反序列化为generics类型java对象的列表
同样的想法,但我们有一个不同的特殊类来帮助Gson进行反序列化:
public List getList(String json, SomeObject someObjectWithGenericType) { Class cl = getTypeClassOfObject(someObjWithGenericType); List list = gson.fromJson(json, new ListWithElements (cl)); return list; } private class ListWithElements implements ParameterizedType { private Class elementsClass; public ListWithElements(Class elementsClass) { this.elementsClass = elementsClass; } public Type[] getActualTypeArguments() { return new Type[] {elementsClass}; } public Type getRawType() { return List.class; } public Type getOwnerType() { return null; } }
奖金
正如您将在这里看到的, someObjectWithGenericType
将成为具有generics类型T
的回调。 即使我使用loopj,我确信任何其他异步http客户端都可以用来实现相同的结果。
loopj + Gson with generics:object
public void getObject(String url, HashMap paramsMap, final GetObjectCallback callback) { RequestParams params = convertParams(paramsMap); client.get(url, params, new TextHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, String responseBody) { try { Class cl = getTypeClassOfInterfaceObject(callback); T object = gson.fromJson(responseBody, new Element (cl)); if (object != null) { callback.onSuccess(object); } else { callback.onFailure(); } } catch (Exception e) { e.printStackTrace(); callback.onFailure(); } } @Override public void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) { error.printStackTrace(); callback.onFailure(); } }); } private RequestParams convertParams(HashMap paramsMap) { RequestParams params = new RequestParams(); if (paramsMap != null) { for (String key : paramsMap.keySet()) { params.put(key, paramsMap.get(key)); } } return params; } public interface GetObjectCallback { void onSuccess(T item); void onFailure(); }
loopj + Gson with generics:list
public void getList(String url, HashMap paramsMap, final GetListCallback callback) { RequestParams params = convertParams(paramsMap); client.get(url, params, new TextHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, String responseBody) { try { Class cl = getTypeClassOfInterfaceObject(callback); List list = gson.fromJson(responseBody, new ListWithElements (cl)); if (list != null) { callback.onSuccess(list); } else { callback.onFailure(); } } catch (Exception e) { e.printStackTrace(); callback.onFailure(); } } @Override public void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) { error.printStackTrace(); callback.onFailure(); } }); } public interface GetListCallback { void onSuccess(List list); void onFailure(); }
用法:对象
api.getObject(URL, paramsMap, new GetObjectCallback() { @Override public void onSuccess(NewsItem item) { // do something } @Override public void onFailure() { // do something } });
用法:清单
api.getList(URL, paramsMap, new GetListCallback() { @Override public void onSuccess(List list) { // do something } @Override public void onFailure() { // do something } });
任何改进都非常受欢迎!