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对象 - 从不相反。)
答案 0 :(得分:191)
2015年10月, Gson版本2.4 (changelog)添加了在反序列化时为@SerializedName
使用备用/多个名称的功能。不再需要自定义TypeAdapter了!
<强>用法:强>
@SerializedName(value="name", alternate={"person", "user"})
https://google.github.io/gson/apidocs/com/google/gson/annotations/SerializedName.html
答案 1 :(得分:25)
不支持在Gson中为字段定义多个@SerializedName
注释。
原因:默认情况下,使用LinkedHashMap管理反序列化,并且键由传入的json的字段名称(不是自定义类的字段名称或序列化名称)定义,并且有一对一的映射。您可以在ReflectiveTypeAdapterFactory
班级的内部Adapter<T>
read(JsonReader in)
方法中查看实施(反序列化的工作原理)。
<强>解决方案:强>
您可以编写一个自定义TypeAdapter来处理name
,person
和user
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"}
编辑2016.04.06:正如@Mathieu Castets写的那样,他现在得到了支持。 (这是这个问题的正确答案。)
public abstract String [] alternate
返回:替代名称 反序列化时的字段
默认值: {}
答案 2 :(得分:6)
科特林粉丝
@SerializedName(value="name", alternate= ["person", "user"])
答案 3 :(得分:3)
我在下面使用了KOTLIN,但无法正常工作
@SerializedName(value="name", alternate= ["person", "user"])
所以我编辑了它,在这里效果很好!
@SerializedName(value="name", alternate= arrayOf("person", "user"))