Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Gson反序列化ConcurrentMap_Java_Json_Gson - Fatal编程技术网

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中的类型擦除而无法使用的类型的信息。Generified
TypeAdapter
是错误的。@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中的类型擦除而无法使用的类型的信息。Generified
TypeAdapter
是错误的。@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)