反序列化Gson中的通用列表
我想编写一个generics函数,用Gson反序列化generics类型List,代码如下:
private List GetListFromFile(String filename) { //Read textfile BufferedReader reader; String data=""; try { reader = new BufferedReader(new FileReader(filename)); data = reader.readLine(); reader.close(); } catch (FileNotFoundException ex) { } catch (IOException ex) { } if (data == null) { List Spiel = new ArrayList(); return Spiel; } else { //get list with Deserialise Gson gson = new Gson(); List something = gson.fromJson(data, new TypeToken<List>(){}.getType()); return something; } }
但这段代码不起作用,我得到一个奇怪的结构,但不是我的类型列表
当我使用时:
List something = gson.fromJson(data, new TypeToken<List>(){}.getType());
我工作我得到一个List
!!
但我需要一个通用function,我该如何解决?
关心rubiktubik
没有将实际类型的T
(如Class
)传递给您的方法,就无法做到这一点。
但是如果你明确地传递它,你可以为List
创建一个TypeToken
,如下所示:
private List GetListFromFile(String filename, Class elementType) { ... TypeToken> token = new TypeToken>() {}; List something = gson.fromJson(data, token.getType()); ... }
也可以看看:
-
TypeToken
使用TypeToken的方法不起作用。
new TypeToken>()
因为generics(类型擦除)和reflection的工作方式是不可能的。 整个TypeToken
hack有效,因为Class#getGenericSuperclass()
执行以下操作
返回表示此Class表示的实体(类,接口,基本类型或void)的直接超类的Type。
如果超类是参数化类型,则返回的Type对象必须准确反映源代码中使用的实际类型参数。
换句话说,如果它看到ArrayList
,那么它将返回ParameterizedType
,你将无法提取类型变量T
将具有的编译时间值。
Type
和ParameterizedType
都是接口。 您可以提供自己实现的实例。
所以,你有两个选择:
选项1:自己实现java.lang.reflect.ParameterizedType
并将其传递给Gson。
private static class ListParameterizedType implements ParameterizedType { private Type type; public ListParameterizedType(Type type) { this.type = type; } @Override public Type[] getActualTypeArguments() { return new Type[] {type}; } @Override public Type getRawType() { return ArrayList.class; } @Override public Type getOwnerType() { return null; } // implement equals method too! (as per javadoc) }
那简单地说:
Type type = new ListParameterizedType(clazz); List list = gson.fromJson(json, type);
请注意,根据javadoc ,还应实现equals方法。
选项2:手动解析列表,然后为每个元素使用Gson
public List listEntity(Class clazz) throws WsIntegracaoException { try { // Consuming remote method String strJson = getService().listEntity(clazz.getName()); JsonParser parser = new JsonParser(); JsonArray array = parser.parse(strJson).getAsJsonArray(); List lst = new ArrayList (); for(final JsonElement json: array){ T entity = GSON.fromJson(json, clazz); lst.add(entity); } return lst; } catch (Exception e) { throw new WsIntegracaoException( "WS method error [listEntity()]", e); } }