Java 每个字段有多个 GSON @SerializedName?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25707728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:58:37  来源:igfitidea点击:

Multiple GSON @SerializedName per field?

javajsongson

提问by Gus

Is there any way in Gson to map multiple JSON fields to a single Java object member variable?

Gson 有没有办法将多个 JSON 字段映射到单个 Java 对象成员变量?

Let's say I have a Java class...

假设我有一个 Java 类...

public class MyClass {
    String id;
    String name;
}

I want to use this single class with two different services. However, these two services differ in how they return their data...

我想将这个单一的类与两种不同的服务一起使用。但是,这两种服务在返回数据的方式上有所不同......

{ "id": 2341, "person": "Bob" }

... and ...

... 和 ...

{ "id": 5382, "user": "Mary" }

... respectively.

... 分别。

Is there any way to map both the "person"and "user"fields in the JSON string to the namefield in the Java object?

有没有办法将 JSON 字符串中的"person""user"字段映射到nameJava 对象中的字段?

(Note: I only ever need to convert from JSON string to Java object - never the other way around.)

(注意:我只需要从 JSON 字符串转换为 Java 对象 - 从不反过来。)

回答by Devrim

It is not supported to define multiple @SerializedNameannotations to a field at Gson.

@SerializedNameGson不支持为一个字段定义多个注释。

Reason:By default Deserialization is managed with a LinkedHashMap and the keys are defined by incoming json's field names (not the custom class's field names or the serializedNames) and there is a one to one mapping. You can see the implementation(how deserialization works) at ReflectiveTypeAdapterFactoryclass's inner class Adapter<T>'s read(JsonReader in)method.

原因:默认情况下,反序列化由 LinkedHashMap 管理,键由传入的 json 字段名称(不是自定义类的字段名称或序列化名称)定义,并且存在一对一映射。您可以在ReflectiveTypeAdapterFactory类的内部类Adapter<T>read(JsonReader in)方法中看到实现(反序列化是如何工作的)。

Solution:You can write a custom TypeAdapterwhich handles name, personand userjson tags and maps them to name field of your custom class MyClass:

解决办法:你可以写一个自定义的TypeAdapter负责处理namepersonuserJSON标签,并将它们映射到您的自定义类的名称字段MyClass

class MyClassTypeAdapter extends TypeAdapter<MyClass> {

    @Override
    public MyClass read(final JsonReader in) throws IOException {
        final MyClass myClassInstance = new MyClass();

        in.beginObject();
        while (in.hasNext()) {
            String jsonTag = in.nextName();
            if ("id".equals(jsonTag)) {
                myClassInstance.id = in.nextInt();
            } else if ("name".equals(jsonTag) 
                    || "person".equals(jsonTag)
                    || "user".equals(jsonTag)) {
                myClassInstance.name = in.nextString();
            }
        }
        in.endObject();

        return myClassInstance;
    }

    @Override
    public void write(final JsonWriter out, final MyClass myClassInstance)
            throws IOException {
        out.beginObject();
        out.name("id").value(myClassInstance.id);
        out.name("name").value(myClassInstance.name);
        out.endObject();
    }
}

Test case:

测试用例:

    String jsonVal0 = "{\"id\": 5382, \"user\": \"Mary\" }";
    String jsonVal1 = "{\"id\": 2341, \"person\": \"Bob\"}";

    final GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(MyClass.class, new MyClassTypeAdapter());
    final Gson gson = gsonBuilder.create();

    MyClass myClassInstance0 = gson.fromJson(jsonVal0, MyClass.class);
    MyClass myClassInstance1 = gson.fromJson(jsonVal1, MyClass.class);

    System.out.println("jsonVal0 :" + gson.toJson(myClassInstance0));
    // output: jsonVal0 :{"id":5382,"name":"Mary"}

    System.out.println("jsonVal1 :" + gson.toJson(myClassInstance1));
    // output: jsonVal1 :{"id":2341,"name":"Bob"}

Examples about TypeAdapters.

关于类型适配器的示例。

Edit 2016.04.06 :As @Mathieu Castets has written at his answer, it is supported now. (That is the correct answer for this question.)

编辑 2016.04.06 :正如@Mathieu Castets 在他的回答中所写的那样,现在支持它。(这是这个问题的正确答案。)

public abstract String[] alternate
Returns: the alternative names of the field when it is deserialized
Default: {}

public abstract String[] 替代
返回:字段反序列化时的替代名称
默认值:{}

回答by Mathieu Castets

In October 2015, Gson version 2.4(changelog) added the ability to use alternate/multiple names for @SerializedNamewhen deserializing. No more custom TypeAdapter needed!

2015 年 10 月,Gson 2.4 版( changelog) 添加了@SerializedName在反序列化时使用备用/多个名称的功能。不再需要自定义 TypeAdapter!

Usage:

用法:

@SerializedName(value="name", alternate={"person", "user"})

https://www.javadoc.io/doc/com.google.code.gson/gson/2.6.2/com/google/gson/annotations/SerializedName.html

https://www.javadoc.io/doc/com.google.code.gson/gson/2.6.2/com/google/gson/annotations/SerializedName.html

回答by Mostafa Anter

for Kotlinfans

对于Kotlin粉丝

@SerializedName(value="name", alternate= ["person", "user"])

回答by android

For KOTLIN i used below but doesn't work

对于我在下面使用的 KOTLIN 但不起作用

@SerializedName(value="name", alternate= ["person", "user"])

so i edited it and here it works fine!!

所以我编辑了它,在这里它工作正常!!

@SerializedName(value="name", alternate= arrayOf("person", "user"))