Multiple GSON @SerializedName per field?

前端 未结 4 611
盖世英雄少女心
盖世英雄少女心 2020-12-07 19:26

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

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

public class MyClass          


        
相关标签:
4条回答
  • 2020-12-07 20:16

    For KOTLIN i used below but doesn't work

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

    so i edited it and here it works fine!!

    @SerializedName(value="name", alternate= arrayOf("person", "user"))
    
    0 讨论(0)
  • 2020-12-07 20:19

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

    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 ReflectiveTypeAdapterFactory class's inner class Adapter<T>'s read(JsonReader in) method.

    Solution: You can write a custom TypeAdapter which handles name, person and user json tags and maps them to name field of your custom class 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.)

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

    0 讨论(0)
  • 2020-12-07 20:24

    for Kotlin fans

    @SerializedName(value="name", alternate= ["person", "user"])
    
    0 讨论(0)
  • 2020-12-07 20:27

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

    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

    0 讨论(0)
提交回复
热议问题