Java 如何使用Gson反序列化ConcurrentMap
我试图反序列化一个对象,该对象中有一个Java 如何使用Gson反序列化ConcurrentMap,java,json,gson,Java,Json,Gson,我试图反序列化一个对象,该对象中有一个ConcurrentMap,但我得到一个异常 Caused by: java.lang.IllegalArgumentException: Can not set java.util.concurrent.ConcurrentMap field com.example.Row.doubleValues to java.util.LinkedHashMap 我的函数如下所示: T deserialise(final InputStream input, fi
ConcurrentMap
,但我得到一个异常
Caused by: java.lang.IllegalArgumentException: Can not set java.util.concurrent.ConcurrentMap field com.example.Row.doubleValues to java.util.LinkedHashMap
我的函数如下所示:
T deserialise(final InputStream input, final Class<T> type) {
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
InputStreamReader isr = new InputStreamReader(input);
return gson.fromJson(isr, type);
}
public class Row implements Serializable {
private static final long serialVersionUID = 1L; //there's a diff value here
private final String key;
private final ConcurrentMap<String, Double> doubleValues = Maps.newConcurrentMap();
private Map<String, String> writeOnceValues = Maps.newHashMap();
...
}
这是我建议的带有
TypeAdapter
的解决方案。在向您展示代码之前,我必须指出,如果字段被解析为字符串,则不应将final
用于字段,因为Gson将尝试为该字段赋值
我更改了行
类,只是为了显示解决方案
public class Row implements Serializable {
private static final long serialVersionUID = 1L; //there's a diff value here
private final String key = "myKey";
private ConcurrentMap<String, Double> doubleValues = Maps.newConcurrentMap();
private Map<String, String> writeOnceValues = Maps.newHashMap();
@Override
public String toString() {
return "Row [key=" + key.getClass() + ", doubleValues=" + doubleValues.getClass()
+ ", writeOnceValues=" + writeOnceValues.getClass() + "]";
}
}
还有一种测试方法,我向你们展示了它的工作原理
public static void main(String[] args) {
Gson simpleGson = new Gson();
// deserialize row once to get a suitable JSON string
String s = simpleGson.toJson(new Row());
System.out.println("JSON string: " + s);
Row r;
try{
r = simpleGson.fromJson(s, Row.class);
} catch(Exception e){
System.out.println("Oh no, assignment is not possible");
e.printStackTrace();
}
GsonBuilder gb = new GsonBuilder();
Type aType = new TypeToken<ConcurrentMap<String,Double>>() {}.getType();
gb.registerTypeAdapter(aType, new ConcurrentHashMapTypeAdapter<String, Double>());
Gson gsonWithTypeAdapter = gb.create();
r = gsonWithTypeAdapter.fromJson(s, Row.class);
System.out.println("Now it works");
System.out.println("Row: " +r);
}
这是我建议的带有
TypeAdapter
的解决方案。在向您展示代码之前,我必须指出,如果字段被解析为字符串,则不应将final
用于字段,因为Gson将尝试为该字段赋值
我更改了行
类,只是为了显示解决方案
public class Row implements Serializable {
private static final long serialVersionUID = 1L; //there's a diff value here
private final String key = "myKey";
private ConcurrentMap<String, Double> doubleValues = Maps.newConcurrentMap();
private Map<String, String> writeOnceValues = Maps.newHashMap();
@Override
public String toString() {
return "Row [key=" + key.getClass() + ", doubleValues=" + doubleValues.getClass()
+ ", writeOnceValues=" + writeOnceValues.getClass() + "]";
}
}
还有一种测试方法,我向你们展示了它的工作原理
public static void main(String[] args) {
Gson simpleGson = new Gson();
// deserialize row once to get a suitable JSON string
String s = simpleGson.toJson(new Row());
System.out.println("JSON string: " + s);
Row r;
try{
r = simpleGson.fromJson(s, Row.class);
} catch(Exception e){
System.out.println("Oh no, assignment is not possible");
e.printStackTrace();
}
GsonBuilder gb = new GsonBuilder();
Type aType = new TypeToken<ConcurrentMap<String,Double>>() {}.getType();
gb.registerTypeAdapter(aType, new ConcurrentHashMapTypeAdapter<String, Double>());
Gson gsonWithTypeAdapter = gb.create();
r = gsonWithTypeAdapter.fromJson(s, Row.class);
System.out.println("Now it works");
System.out.println("Row: " +r);
}
你能显示你想反序列化到的类的相关部分吗?@Katona添加了一个例子一个明显的解决方案是将
doubleValues
的类型从ConcurrentMap
更改为Map
,你真的需要吗?否则,您将需要自定义反序列化,请参见问题,问题类似但不一致,我认为解决方案(InstanceCreator
)这里可能有用。你能显示你想要反序列化到的类的相关部分吗?@Katona添加了一个例子一个明显的解决方案是将双值的类型从ConcurrentMap
更改为Map
,你真的需要吗?否则,您将需要自定义反序列化,请参见问题,问题类似但不一致,我认为解决方案(InstanceCreator
)可能在这里工作。在ConcurrentHashMapTypeAdapter
类中TypeAdapterFactory
的目的是什么,如果在示例中的任何地方都没有使用,Gson中的
TypeAdapter机制专门设计用于提供有关由于Java中的类型擦除而无法使用的类型的信息。GenerifiedTypeAdapter
是错误的。@andrybak已经三年了。至少给我一天的时间来检查答案。@andrybak:工厂场地没用,我不记得我为什么把它放在那里,准备搬走。关于我使用TypeAdapter的解决方案,如果您有一种更优雅的方式来解决没有TypeAdapter的OP问题,我很高兴看到您的答案并与我的答案进行比较:)。我总是渴望学习:)。这里没有被动攻击的意图。@giampaolo:我正在使用我自己的类作为ConcurrentMap中的一个键,当我打算使用gson反序列化时,我得到了java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap在com.google.gson.internal.LinkedTreeMap.find(LinkedTreeMap.java:164)上是不可比的在com.google.gson.internal.LinkedTreeMap.put(LinkedTreeMap.java:94)上,在ConcurrentHashMapTypeAdapter
类中,TypeAdapterFactory
的目的是什么,如果在示例中的任何地方都没有使用,Gson中的TypeAdapter机制专门设计用于提供有关由于Java中的类型擦除而无法使用的类型的信息。GenerifiedTypeAdapter
是错误的。@andrybak已经三年了。至少给我一天的时间来检查答案。@andrybak:工厂场地没用,我不记得我为什么把它放在那里,准备搬走。关于我使用TypeAdapter的解决方案,如果您有一种更优雅的方式来解决没有TypeAdapter的OP问题,我很高兴看到您的答案并与我的答案进行比较:)。我总是渴望学习:)。这里没有被动攻击的意图。@giampaolo:我正在使用我自己的类作为ConcurrentMap中的一个键,当我打算使用gson反序列化时,我得到了java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap在com.google.gson.internal.LinkedTreeMap.find(LinkedTreeMap.java:164)上是不可比的位于com.google.gson.internal.LinkedTreeMap.put(LinkedTreeMap.java:94)