2014-09-07 6 views
54

Esiste un modo in Gson per mappare più campi JSON su una singola variabile membro dell'oggetto Java?Più GSON @SerializedName per campo?

Diciamo che ho una classe Java ...

public class MyClass { 
    String id; 
    String name; 
} 

voglio usare questo singolo classe con due servizi diversi. Tuttavia, questi due servizi si differenziano per il modo in cui ritornano i loro dati ...

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

... e ...

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

... rispettivamente.

Esiste un modo per mappare entrambi i campi "person" e "user" nella stringa JSON nel campo name nell'oggetto Java?

. (Nota: ho sempre e solo bisogno di convertire da stringa JSON per oggetto Java - non il contrario)

+0

Ecco spiegazione semplice e perfetta https://futurestud.io/tutorials/gson-model-annotations-multiple-deserialization-names-with-serializedname –

risposta

20

Non è supportato per definire più @SerializedName annotazioni a un campo a GSON.

Motivo: Per deserializzazione impostazione predefinita è gestito con un LinkedHashMap e le chiavi sono definiti da nomi dei campi di JSON in entrata (i nomi dei campi non della classe personalizzata o serializedNames) e c'è una mappatura uno a uno. È possibile visualizzare l'implementazione (come funziona la deserializzazione) nel metodo ReflectiveTypeAdapterFactory della classe interna-60-40-100-56-del codice categoria della classe.

Soluzione: È possibile scrivere un costume TypeAdapter che gestisce name, person e user tag JSON e li associa al campo del nome della classe personalizzata MyClass: caso

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(); 
    } 
} 

prova:

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.

Modifica 2016/04/06: Come @Mathieu Castets ha scritto alla sua risposta, ora è supportato. (Questa è la risposta giusta per questa domanda.)

public abstract String [] alterni
Restituisce: i nomi alternativi di il campo quando viene deserializzato
predefinito: {}

+0

Ecco la spiegazione semplice e perfetta https://futurestud.io/tutorials/gson-model-annotations-multiple-deserialization-names-with-serializedname –

130

Nell'ottobre 2015, versione di Gson 2.4 (changelog) ha aggiunto la possibilità di utilizzare nomi alternativi/multipli per @SerializedName durante la deserializzazione. Non è necessario più TypeAdapter personalizzato!

Usage:

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

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

+0

Great. Grazie. – Mulgard

+1

Salva da un'altra soluzione stupida e alcune condizioni. Grazie :) –

+0

Ecco la spiegazione semplice e perfetta https://futurestud.io/tutorials/gson-model-annotations-multiple-deserialization-names-with-serializedname –