每个字段多个GSON @SerializedName?

时间:2014-09-07 06:35:03

标签: java json gson

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对象 - 从不相反。)

4 个答案:

答案 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来处理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"}

Examples about TypeAdapters.

编辑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"))