2011-10-05 9 views
39

ho le seguenti classioggetto maniglia GSON o array

public class MyClass { 
    private List<MyOtherClass> others; 
} 

public class MyOtherClass { 
    private String name; 
} 

E devo JSON che può assomigliare a questo

{ 
    others: { 
    name: "val" 
    } 
} 

o questo

{ 
    others: [ 
    { 
     name: "val" 
    }, 
    { 
     name: "val" 
    } 
    ] 
} 

mi piacerebbe piace essere in grado di utilizzare lo stesso MyClass per entrambi questi formati JSON. C'è un modo per farlo con Gson?

+1

La domanda è: chi genera JSON come questo? E 'valido Json? Se lo è, Gson dovrebbe gestirlo. In caso contrario, la soluzione "reale" dovrebbe essere quella di fissare il produttore. – Nilzor

+5

Sono assolutamente d'accordo che questo non è un ottimo modo per scrivere JSON. Sfortunatamente, non abbiamo sempre il controllo sui dati che consumiamo, quindi fissare il produttore non è sempre un'opzione. È JSON valido, poiché JSON non ha schema. –

risposta

69

Mi è venuta una risposta.

private static class MyOtherClassTypeAdapter implements JsonDeserializer<List<MyOtherClass>> { 
    public List<MyOtherClass> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) { 
     List<MyOtherClass> vals = new ArrayList<MyOtherClass>(); 
     if (json.isJsonArray()) { 
      for (JsonElement e : json.getAsJsonArray()) { 
       vals.add((MyOtherClass) ctx.deserialize(e, MyOtherClass.class)); 
      } 
     } else if (json.isJsonObject()) { 
      vals.add((MyOtherClass) ctx.deserialize(json, MyOtherClass.class)); 
     } else { 
      throw new RuntimeException("Unexpected JSON type: " + json.getClass()); 
     } 
     return vals; 
    } 
} 

un'istanza di un oggetto come questo GSON

Type myOtherClassListType = new TypeToken<List<MyOtherClass>>() {}.getType(); 

Gson gson = new GsonBuilder() 
     .registerTypeAdapter(myOtherClassListType, new MyOtherClassTypeAdapter()) 
     .create(); 

Questo TypeToken è un com.google.gson.reflect.TypeToken.

Potete leggere qui la soluzione:

https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener

+0

Grazie, funziona perfettamente. Avevo un caso in cui il JSON restituiva un singolo oggetto o un insieme di essi. – gnosio

+0

Grazie. È grandioso Avevo bisogno di due diversi TypeAdapters quindi li ho concatenati aggiungendo un altro .registerTypeAdapter – tristan2468

+5

Perché Gson non sta mettendo solo le annotazioni per accettare array o oggetti dello stesso formato? Questo è molto richiesto. –

8

Grazie tre tazze per la soluzione!

la stessa cosa con tipo generico nel caso in cui ce n'è bisogno per più tipi:

public class SingleElementToListDeserializer<T> implements JsonDeserializer<List<T>> { 

private final Class<T> clazz; 

public SingleElementToListDeserializer(Class<T> clazz) { 
    this.clazz = clazz; 
} 

public List<T> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
    List<T> resultList = new ArrayList<>(); 
    if (json.isJsonArray()) { 
     for (JsonElement e : json.getAsJsonArray()) { 
      resultList.add(context.<T>deserialize(e, clazz)); 
     } 
    } else if (json.isJsonObject()) { 
     resultList.add(context.<T>deserialize(json, clazz)); 
    } else { 
     throw new RuntimeException("Unexpected JSON type: " + json.getClass()); 
    } 
    return resultList; 
    } 
} 

e la configurazione GSON:

Type myOtherClassListType = new TypeToken<List<MyOtherClass>>() {}.getType(); 
SingleElementToListDeserializer<MyOtherClass> adapter = new SingleElementToListDeserializer<>(MyOtherClass.class); 
Gson gson = new GsonBuilder() 
    .registerTypeAdapter(myOtherClassListType, adapter) 
    .create(); 
0

Partendo tre tazze risposta, ho il seguente che consente al JsonArray può essere deserializzato direttamente come array.

static public <T> T[] fromJsonAsArray(Gson gson, JsonElement json, Class<T> tClass, Class<T[]> tArrClass) 
     throws JsonParseException { 

    T[] arr; 

    if(json.isJsonObject()){ 
     //noinspection unchecked 
     arr = (T[]) Array.newInstance(tClass, 1); 
     arr[0] = gson.fromJson(json, tClass); 
    }else if(json.isJsonArray()){ 
     arr = gson.fromJson(json, tArrClass); 
    }else{ 
     throw new RuntimeException("Unexpected JSON type: " + json.getClass()); 
    } 

    return arr; 
} 

Usage:

String response = "......."; 

    JsonParser p = new JsonParser(); 
    JsonElement json = p.parse(response); 
    Gson gson = new Gson(); 
    MyQuote[] quotes = GsonUtils.fromJsonAsArray(gson, json, MyQuote.class, MyQuote[].class);