Plusieurs GSON @SerializedName par champ?

Existe-t-il un moyen dans Gson de mapper plusieurs champs JSON sur une seule variable membre d’object Java?

Disons que j’ai une classe Java …

public class MyClass { Ssortingng id; Ssortingng name; } 

Je souhaite utiliser cette classe unique avec deux services différents. Cependant, ces deux services diffèrent dans la façon dont ils renvoient leurs données …

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

… et …

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

… respectivement.

Existe-t-il un moyen de mapper les champs "person" et "user" de la chaîne JSON sur le champ name de l’object Java?

(Remarque: je n’ai jamais besoin de convertir une chaîne JSON en object Java – jamais l’inverse.)

En octobre 2015, Gson version 2.4 ( changelog ) a ajouté la possibilité d’utiliser des noms alternatifs / multiples pour @SerializedName lors de la désérialisation. Plus besoin de TypeAdapter personnalisé!

Usage:

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

https://google.github.io/gson/apidocs/com/google/gson/annotations/SerializedName.html

Il n’est pas pris en charge pour définir plusieurs annotations @SerializedName sur un champ chez Gson.

Raison: Par défaut, la désérialisation est gérée avec un LinkedHashMap et les clés sont définies par les noms de champs entrants de json (pas les noms de champs de la classe personnalisée ou les noms de série) et il existe un mappage un à un. Vous pouvez voir l’implémentation (comment fonctionne la désérialisation) à la classe interne de la classe ReflectiveTypeAdapterFactory , la méthode de read(JsonReader in) Adapter read(JsonReader in) .

Solution: Vous pouvez écrire un TypeAdapter personnalisé qui gère user balises json name , person et user et les mappe au champ de nom de votre classe personnalisée MyClass :

 class MyClassTypeAdapter extends TypeAdapter { @Override public MyClass read(final JsonReader in) throws IOException { final MyClass myClassInstance = new MyClass(); in.beginObject(); while (in.hasNext()) { Ssortingng 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.nextSsortingng(); } } 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(); } } 

Cas de test:

  Ssortingng jsonVal0 = "{\"id\": 5382, \"user\": \"Mary\" }"; Ssortingng 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"} 

Exemples sur TypeAdapters.

Edit 04.04.2016: Comme @Mathieu Castets a écrit à sa réponse, il est maintenant supporté. (C’est la bonne réponse à cette question.)

public abstract Ssortingng [] alternative
Retourne: les noms alternatifs du champ quand il est désérialisé
Par défaut: {}