Java 如何使用GSON反序列化自定义映射

Java 如何使用GSON反序列化自定义映射,java,serialization,gson,deserialization,apache-commons-collection,Java,Serialization,Gson,Deserialization,Apache Commons Collection,我正在使用Apache Collection的BidiMap,它提供了DualHashBidiMap类。我必须在这个项目中使用这个类 它的序列化没有问题。但我对反序列化有问题 下面是一个示例类: package com.description; import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; public class

我正在使用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;
    }
}

为什么需要使用BidiMap

检查以下各项:

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

顺便说一下:您的JSON不是
Map
,而是
Map
Map
{1:“手套”,“90:“靴子”}


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

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

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));
            }
        };
    }
}
现在您可以运行您的示例了,它应该可以工作了

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)
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));
            }
        };
    }
}
GsonBuilder b = new GsonBuilder().registerTypeAdapterFactory(new BidiMapTypeAdapterFactory());
Gson gson = b.create();