Google Gson - deserialize list<class> object? (generic type)
我想通过google gson传输一个列表对象,但我不知道如何反序列化泛型类型。
我在看了这个之后尝试了什么(俾路支的回答):
1 | MyClass mc = new Gson().fromJson(result, new List<MyClass>(){}.getClass()); |
但是我在Eclipse中得到一个错误,说"type new list()must implement the inherited abstract method…",如果我使用快速修复,我会得到一个超过20个方法存根的怪物。
我很确定有一个更简单的解决方案,但我似乎找不到它!
编辑:
现在我有
1 2 3 4 5 | Type listType = new TypeToken<List<MyClass>>() { }.getType(); MyClass mc = new Gson().fromJson(result, listType); |
但是,在"fromjson"行中,我确实得到了以下异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | java.lang.NullPointerException at org.apache.harmony.luni.lang.reflect.ListOfTypes.length(ListOfTypes.java:47) at org.apache.harmony.luni.lang.reflect.ImplForType.toString(ImplForType.java:83) at java.lang.StringBuilder.append(StringBuilder.java:203) at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:56) at com.google.gson.JsonDeserializationVisitor.invokeCustomDeserializer(JsonDeserializationVisitor.java:88) at com.google.gson.JsonDeserializationVisitor.visitUsingCustomHandler(JsonDeserializationVisitor.java:76) at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:106) at com.google.gson.JsonDeserializationContextDefault.fromJsonArray(JsonDeserializationContextDefault.java:64) at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:49) at com.google.gson.Gson.fromJson(Gson.java:568) at com.google.gson.Gson.fromJson(Gson.java:515) at com.google.gson.Gson.fromJson(Gson.java:484) at com.google.gson.Gson.fromJson(Gson.java:434) |
我确实捕获了jsonParseExceptions,"result"不为空。
我用调试器检查了ListType,得到了以下结果:
- 列表类型
- args=列表类型
- 列表=空
- resolvedtypes=类型[1]
- 加载器=路径类加载器
- ownerType0=空
- ownerTypeRes=空
- 类=
- RAWType名称="java. U.L.ARayLIST"
- args=列表类型
因此,"getClass"调用似乎没有正常工作。有什么建议吗…?
编辑2:我查看了GSON用户指南。它提到了将泛型类型解析为JSON时应该发生的运行时异常。我做的是"错误的"(上面没有显示),就像在示例中一样,但根本没有得到那个异常。所以我按照用户指南中的建议更改了序列化。不过,没有帮助。
EdTe3:已解决,请参阅下面的答案。
反序列化泛型集合的方法:
1 2 3 4 5 6 7 | import java.lang.reflect.Type; import com.google.gson.reflect.TypeToken; ... Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType(); List<YourClass> yourClassList = new Gson().fromJson(jsonArray, listType); |
由于评论中有几个人提到了它,下面是如何使用
由于类型擦除,>() {}.getType()
有关更多信息,请参阅
另一种方法是使用数组作为类型,例如:
1 | MyClass[] mcArray = gson.fromJson(jsonString, MyClass[].class); |
这样可以避免类型对象带来的所有麻烦,如果确实需要列表,则可以通过以下方式将数组转换为列表:
1 |
imho这是更可读的。
为了使其成为一个实际的列表(可以修改,参见
1 |
请参阅本帖。GSON的Java类型泛型
我有更好的解决办法。这是列表的包装器类,这样包装器就可以存储列表的确切类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class ListOfJson<T> implements ParameterizedType { private Class<?> wrapped; public ListOfJson(Class<T> wrapper) { this.wrapped = wrapper; } @Override public Type[] getActualTypeArguments() { return new Type[] { wrapped }; } @Override public Type getRawType() { return List.class; } @Override public Type getOwnerType() { return null; } } |
然后,代码可以很简单:
1 2 3 4 | public static <T> List<T> toList(String json, Class<T> typeClass) { return sGson.fromJson(json, new ListOfJson<T>(typeClass)); } |
WEP,实现相同结果的另一种方法。我们使用它是为了它的可读性。
而不是做这个难读的句子:
1 2 | Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType(); List<YourClass> list = new Gson().fromJson(jsonArray, listType); |
创建一个扩展对象列表的空类:
1 | public class YourClassList extends ArrayList<YourClass> {} |
并在解析JSON时使用它:
1 | List<YourClass> list = new Gson().fromJson(jsonArray, YourClassList.class); |
由于
1 2 3 4 |
实例使用
1 2 |
1 2 3 4 5 6 |
例子:
1 | getList(MyClass[].class,"[{...}]"); |
对于Kotlin来说:
1 2 3 4 | import java.lang.reflect.Type import com.google.gson.reflect.TypeToken ... val type = object : TypeToken<ArrayList<T>>() {}.type |
或者,这里有一个有用的函数:
1 2 3 | fun <T> buildType(): Type { return object : TypeToken<ArrayList<T>>() {}.type } |
然后,使用:
1 | val type = buildType<YourMagicObject>() |
当它回答我原来的问题时,我接受了医生的回答,但是如果有人再次遇到这个问题,我也会回答我问题的后半部分:
我所描述的nullpointererror与列表本身无关,与它的内容无关!
"MyClass"类没有"no args"构造函数,也没有超类构造函数。一旦我在myClass及其超类中添加了一个简单的"myClass()"构造函数,所有的工作都很好,包括Doc_建议的列表序列化和反序列化。
下面是一个处理动态定义类型的解决方案。技巧是使用array.newInstance()创建适当类型的数组。
1 2 3 4 5 6 7 8 | public static <T> List<T> fromJsonList(String json, Class<T> clazz) { Object [] array = (Object[])java.lang.reflect.Array.newInstance(clazz, 0); array = gson.fromJson(json, array.getClass()); List<T> list = new ArrayList<T>(); for (int i=0 ; i<array.length ; i++) list.add(clazz.cast(array[i])); return list; } |
我想再加一个可能性。如果不想使用typetoken,并且想将JSON对象数组转换为arraylist,那么可以这样继续:
如果您的JSON结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | { "results": [ { "a": 100, "b":"value1", "c": true }, { "a": 200, "b":"value2", "c": false }, { "a": 300, "b":"value3", "c": true } ] |
}
你的班级结构是:
1 2 3 4 5 6 7 8 9 | public class ClassName implements Parcelable { public ArrayList<InnerClassName> results = new ArrayList<InnerClassName>(); public static class InnerClassName { int a; String b; boolean c; } } |
然后你可以像这样分析它:
1 2 3 | Gson gson = new Gson(); final ClassName className = gson.fromJson(data, ClassName.class); int currentTotal = className.results.size(); |
现在可以访问classname对象的每个元素。
请参阅示例2了解GSON的"类型"类理解。
示例1:在这个反序列化表达式中,我们使用了employee[]数组并获取详细信息
1 2 3 4 5 6 7 8 9 10 11 12 | public static void deserializeResturant(){ String empList ="[{"name":"Ram","empId":1},{"name":"Surya","empId":2},{"name":"Prasants","empId":3}]"; Gson gson = new Gson(); Employee[] emp = gson.fromJson(empList, Employee[].class); int numberOfElementInJson = emp.length(); System.out.println("Total JSON Elements" + numberOfElementInJson); for(Employee e: emp){ System.out.println(e.getName()); System.out.println(e.getEmpId()); } } |
例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //Above deserilizeResturant used Employee[] array but what if we need to use List<Employee> public static void deserializeResturantUsingList(){ String empList ="[{"name":"Ram","empId":1},{"name":"Surya","empId":2},{"name":"Prasants","empId":3}]"; Gson gson = new Gson(); // Additionally we need to se the Type then only it accepts List<Employee> which we sent here empTypeList Type empTypeList = new TypeToken<ArrayList<Employee>>(){}.getType(); List<Employee> emp = gson.fromJson(empList, empTypeList); int numberOfElementInJson = emp.size(); System.out.println("Total JSON Elements" + numberOfElementInJson); for(Employee e: emp){ System.out.println(e.getName()); System.out.println(e.getEmpId()); } } |
在我的例子中,@uncaught欷uexceptions的答案不起作用,我不得不使用
1 2 |
我喜欢Kays1的答案,但我无法实现。所以我用他的概念建立了自己的版本。
1 2 3 4 5 6 7 |
用途:
1 | List<MyClass> MyList= JsonListHelper.getList(jsonArrayString); |