我对gson反序列化中的集合有疑问
结果:
第1行:编译没有任何错误。
第2行:它编译没有任何错误。打印[1.0,2.0,3.0,4.0]。
第2行:它抛出“线程中的异常”main“java.lang.ClassCastException:java.lang.Double无法强制转换为gsonUserGuide.com.google.sites.A”
我的问题: 我知道我可以正确指定类型如下。
ArrayList<Integer> aList = gson.fromJson(
"[1,2,3,4]", new TypeToken<ArrayList<Integer>>() {}.getType());
但我的问题是,如果它在第3行中抛出java.lang.ClassCastException,为什么它至少在运行时将值加载到aList时不会出错?
代码:
public class OBJConversion {
private final static Gson gson = new Gson();
public static void main(String[] args) {
// Line 1
ArrayList<A> aList = gson.fromJson("[1,2,3,4]", ArrayList.class);
// Line 2
System.out.println("main().aList : " + aList);
// Line 3
System.out.println("main().someString : " + aList.get(0).getSomeString());
}
class A {
String someString = null;
public String getSomeString() {
return someString;
}
public void setSomeString(String someString) {
this.someString = someString;
}
}
}
答案 0 :(得分:2)
这是因为类型信息(<A>
中的ArrayList<A>
)在运行时不再可用。通用类型在编译期间专门使用,并且被删除&#34;之后,代码最终被编译成类似
ArrayList aList = gson.fromJson("[1,2,3,4]", ArrayList.class);
(注意删除声明中的<A>
类型参数)这就是为什么你必须在运行时提供类型信息(通过&#34;类型标记&#34;),如果你想让代码真的安全。类型信息仅在特殊情况下可用(实际上由类型标记实现使用)。
答案 1 :(得分:2)
使用GSON时,这是Collections Limitations之一:
您可以序列化任意对象的集合,但可以不反序列化,因为用户无法指示生成的对象的类型。
GSON将gson.fromJson("[1,2,3,4]", ArrayList.class)
解释为基元列表(它无法从ArrayList<A>
告诉您需要类型A
,因为类型信息在运行时丢失了)。 GSON具有different primitives而不是Java,并且没有int
,因此[1,2,3,4]
被视为具有双浮点精度的数字列表,即Java Double
。因此,GSON有效地创建了List<Double>
。
GSON建议three workarounds:
Collection.class
或A
注册类型适配器并使用fromJson(aList, Collection<A>.class)
。例如,选项2看起来像这样:
public class OBJConversion {
public static void main(String[] args) {
Gson gson = new GsonBuilder()
// NOTE: all Lists will be treated as List<A>
.registerTypeAdapter(List.class, new ACollectionAdapter())
.create();
// Line 1
List<A> aList = gson.fromJson("[1,2,3,4]", List.class));
// Line 2
System.out.println("main().aList : " + aList);
// Line 3
System.out.println("main().someString : " + aList.get(0).getSomeString());
}
static class ACollectionAdapter extends TypeAdapter<List<A>> {
@Override
public void write(
JsonWriter out, List<A> value) throws IOException {
out.beginArray();
for (A a : value) {
out.value(a.getSomeString());
}
out.endArray();
}
@Override
public List<A> read(JsonReader in) throws IOException {
List<A> as = new ArrayList<A>();
in.beginArray();
while (in.hasNext()) {
A a = new A();
a.setSomeString(in.nextString());
as.add(a);
}
in.endArray();
return as;
}
}
static class A {
String someString = null;
public String getSomeString() {
return someString;
}
public void setSomeString(String someString) {
this.someString = someString;
}
}
}