每个字段有多个GSON @SerializedName?

nhjlsmyf  于 2022-11-23  发布在  其他
关注(0)|答案(4)|浏览(263)

在Gson中有没有什么方法可以将多个JSON字段Map到单个Java对象成员变量?
假设我有一个Java类...

public class MyClass {
    String id;
    String name;
}

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

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

还有......

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

...分别。
有没有办法将JSON字符串中的"person""user"字段Map到Java对象中的name字段?
(Note:我只需要从JSON字符串转换为Java对象-从来没有相反的方法。)

bqujaahr

bqujaahr1#

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

用法:

java

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

Kotlin

@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

68de4m5k

68de4m5k2#

Kotlin粉丝准备的

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

8dtrkrch3#

不支持为Gson中的字段定义多个@SerializedName注解。

    • 原因:**默认情况下,反序列化是使用LinkedHashMap管理的,关键字由传入json的字段名(而不是自定义类的字段名或serializedNames)定义,并且存在一对一Map。您可以在ReflectiveTypeAdapterFactory类的内部类Adapter<T>read(JsonReader in)方法中查看实现(反序列化如何工作)。
    • 解决方案:**您可以编写一个自定义TypeAdapter,它处理namepersonuser json标记,并将它们Map到自定义类MyClass的name字段:
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();
    }
}
    • 测试用例:**
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.

    • 编辑2016.04.06:**正如@Mathieu Castets在他的回答中所写的,现在支持它。(这是这个问题的正确答案。)
    • 公共抽象字符串[]替代项**

返回:反序列化字段时字段的替代名称

    • 默认值:**{}
cwxwcias

cwxwcias4#

对于Kotlin,我在下面使用,但不起作用

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

所以我编辑了一下,在这里效果很好!!

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

相关问题