Кілька GSON @SerializedName на поле?


104

Чи є в Gson спосіб зіставити кілька полів JSON в одну змінну члена об'єкта Java?

Скажімо, у мене клас Java ...

public class MyClass {
    String id;
    String name;
}

Я хочу використовувати цей єдиний клас з двома різними сервісами. Однак ці дві служби відрізняються тим, як вони повертають свої дані ...

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

... і ...

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

... відповідно.

Чи є спосіб зіставити як "person"і "user"поля в рядку JSON на nameполе в об'єкті Java?

(Примітка. Мені потрібно коли-небудь конвертувати з рядка JSON в об’єкт Java - ніколи навпаки.)


1
Ось просте та ідеальне пояснення futurestud.io/tutorials/…
Atul Bhardwaj

Відповіді:


239

У жовтні 2015 року версія Gson 2.4 ( зміни журналу ) додала можливість використовувати альтернативні / кілька імен для @SerializedNameдесеріалізації. Більше не потрібно використовувати спеціальний тип адаптера!

Використання:

@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


1
Ось просте і досконале пояснення futurestud.io/tutorials/…
Atul Bhardwaj

Дивовижний! Дякую за цю відповідь!
sunlover3

чудова відповідь, дякую!
Дор Рудь

27

Це не підтримується для визначення декількох @SerializedNameанотацій до поля в Gson.

Причина: Десеріалізація за замовчуванням управляється за допомогою LinkedHashMap, а ключі визначаються вхідними іменами полів json (не імена полів користувальницького класу чи serializedNames), і відображення від одного до одного. Ви можете побачити реалізацію (яким чином десеріалізациі роботи) на ReflectiveTypeAdapterFactoryвнутрішній клас класу Adapter<T>«s read(JsonReader in)метод.

Рішення: Ви можете написати користувальницький TypeAdapter, який обробляє name, personта userjson теги та відобразити їх у полі імені вашого спеціального класу 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"}

Приклади про TypeAdapters.

Редагувати 2016.04.06: Як написав @Mathieu Castets у своїй відповіді, його зараз підтримують. (Це правильна відповідь на це питання.)

публічний конспект String [] альтернативний
Повертає: альтернативні назви поля при його деріаріалізації
За замовчуванням: {}


Ось просте і досконале пояснення futurestud.io/tutorials/…
Atul Bhardwaj


8

Для KOTLIN я використовувався нижче, але не працює

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

так що я відредагував це, і тут він працює чудово !!

@SerializedName(value="name", alternate= arrayOf("person", "user"))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.