【问题标题】:How to deserialize custom Map with GSON如何使用 GSON 反序列化自定义地图
【发布时间】:2016-04-15 09:25:38
【问题描述】:

我正在使用 Apache Collection 的 BidiMap,它提供 DualHashBidiMap 类。我必须在项目中使用这个类。

用它序列化没有问题。但是我有反序列化的问题!。

这是一个示例类:

package com.description;

import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;

public class Sample {

    private String id;
    private String adress;

    BidiMap<Integer, String> items = new DualHashBidiMap<Integer, String>();


    public Sample() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    public BidiMap<Integer, String> getItems() {
        return items;
    }

    public void setItems(BidiMap<Integer, String> items) {
        this.items = items;
    }
}

主要方法

Sample sample = new Sample();
        sample.setId("12312xoa01");
        sample.setAdress("Houston, 43.1");
        BidiMap<Integer, String> items = new DualHashBidiMap<Integer, String>();
        items.put(1,  "gloves");
        items.put(90, "boots");
        sample.setItems(items);

        try {
            String result =  gson.toJson(sample);
            System.out.println("result : "+result);
            Sample sample2 = gson.fromJson(result, Sample.class);
            System.out.println("address : "+sample2.getAdress());

        }catch (Exception e){
            e.printStackTrace();
        }

**


**

result : {"id":"12312xoa01","adress":"Houston, 43.1","items":{"1":"gloves","90":"boots"}}
java.lang.IllegalArgumentException: Can not set org.apache.commons.collections4.BidiMap field com.description.Sample.items to java.util.LinkedHashMap
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:741)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:118)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216)
    at com.google.gson.Gson.fromJson(Gson.java:879)
    at com.google.gson.Gson.fromJson(Gson.java:844)
    at com.google.gson.Gson.fromJson(Gson.java:793)
    at com.google.gson.Gson.fromJson(Gson.java:765)
    at Main.main(Main.java:79)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

【问题讨论】:

    标签: java serialization gson deserialization apache-commons-collection


    【解决方案1】:

    这不是那么简单,但可以做到:

    public class BidiMapTypeAdapterFactory implements TypeAdapterFactory {
    
        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            if (!BidiMap.class.isAssignableFrom(type.getRawType())) {
                return null;
            }
            final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
            return new TypeAdapter<T>() {
                @Override
                public void write(JsonWriter out, T value) throws IOException {
                    delegate.write(out, value);
                }
    
                @Override
                public T read(JsonReader in) throws IOException {
                    return (T) new DualHashBidiMap<>((Map) delegate.read(in));
                }
            };
        }
    }
    

    注册 TypeAdapterFactory:

    GsonBuilder b = new GsonBuilder().registerTypeAdapterFactory(new BidiMapTypeAdapterFactory());
    Gson gson = b.create();
    

    现在您可以运行您的示例,它应该可以工作了。

    【讨论】:

      【解决方案2】:

      为什么需要使用 BidiMap?

      检查这些:

      deserializing generics with gson

      How to deserialize a ConcurrentMap with Gson

      稍后尝试使用 Map 或 LinkedHashMap 或手动从 Map 解析为 BidiMap 类型,以检查错误是否仍然存在。编写 TypeAdapter 也是一种选择。

      顺便说一句:您的 JSON 不是 Map&lt;Integer,String&gt; 而是 Map&lt;String,String&gt; 映射 {"1":"gloves","90":"boots"}

      我之前尝试过 GSON,它与 Java 中的本机类型很好地配合使用。我从未尝试过解析其他库,因为我认为您需要一个 TypeAdapter。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-23
        • 2013-09-09
        • 2013-03-09
        • 1970-01-01
        • 1970-01-01
        • 2021-12-24
        • 2014-09-06
        相关资源
        最近更新 更多