gpt4 book ai didi

java - 如何使用 Gson 反序列化 ConcurrentMap

转载 作者:行者123 更新时间:2023-11-29 09:30:24 47 4
gpt4 key购买 nike

我正在尝试反序列化其中包含 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);
}

如何让它正确反序列化 map ?我需要提供自定义反序列化器吗?

请注意,我在同一类中同时拥有常规 MapsConcurrentMaps。我也是序列化该类的人,因此,如果我可以提供一个自定义序列化程序来指定并发映射的类型,然后提供一个反序列化程序来指定如何将它们创建为应该工作的对象。

更新:我正在反序列化的类如下所示:

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 会尝试为该字段赋值。

我更改了 Row 类,只是为了展示解决方案。

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() + "]";
}

}

和我基本上使用标准解析但返回 ConcurrentHashMap 的类型适配器。

public final class ConcurrentHashMapTypeAdapter<K,V> extends TypeAdapter<ConcurrentMap<K,V>> {

@Override
public synchronized ConcurrentMap<K,V> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
Type aType = new TypeToken<LinkedTreeMap<K,V>>() {}.getType();
Gson g = new Gson();
LinkedTreeMap<K,V> ltm = g.fromJson(in, aType);
return new ConcurrentHashMap<K,V>(ltm);
}

@Override
public synchronized void write(JsonWriter out, ConcurrentMap<K, V> value) throws IOException {
Gson g = new Gson();
out.value(g.toJson(value));
}
}

还有一个测试方法,我会向您展示它是有效的。

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);
}

这是我的处决:

JSON string: {"key":"myKey","doubleValues":{},"writeOnceValues":{}}
Oh no, assignment is not possible
java.lang.IllegalArgumentException: Can not set java.util.concurrent.ConcurrentMap field stackoverflow.questions.q18856793.Row.doubleValues to com.google.gson.internal.LinkedTreeMap
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(Unknown Source)
at java.lang.reflect.Field.set(Unknown Source)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:95)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.Gson.fromJson(Gson.java:803)
at com.google.gson.Gson.fromJson(Gson.java:768)
at com.google.gson.Gson.fromJson(Gson.java:717)
at com.google.gson.Gson.fromJson(Gson.java:689)
at stackoverflow.questions.q18856793.Q18856793.main(Q18856793.java:23)
Now it works
Row: Row [key=class java.lang.String, doubleValues=class java.util.concurrent.ConcurrentHashMap, writeOnceValues=class com.google.gson.internal.LinkedTreeMap]

关于java - 如何使用 Gson 反序列化 ConcurrentMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18856793/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com