每个字段多个 GSON@SerializedName? ?

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

假设我有一个 Java 类。

public class MyClass {
String id;
String name;
}

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

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

还有..。

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

... 分别。

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

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

53735 次浏览

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

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

解决方案: 您可以编写一个自定义 字体适配器,它处理 namepersonuser json 标记,并将它们映射到自定义类 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();
}
}

测试案例:

    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"}

关于 TypeAdapter 的示例。

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

Public 抽象字符串[] Alternate
返回: 的替代名称 反序列化后的字段
< b > 预设值:{}

2015年10月,Gson 版本2.4(更改日志)增加了在反序列化时为 @SerializedName使用替代/多重名称的能力。不再需要自定义 TypeAdapter!

用法:

爪哇咖啡

@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

科特林的粉丝

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

对于 KOTLIN 我使用下面,但不工作

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

所以我编辑了它,在这里它工作得很好! !

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