2015-02-04 20 views
20

Ho fatto questa domanda in un'altra domanda oggi, ma temo che non otterrà alcuna soluzione a causa di come è stata formulata.Gson - Stesso nome del campo, diversi tipi

Ho un ingresso JSON che presenta i seguenti dati:

Json

Come si può vedere, l'elemento option_value è un array in un oggetto e una semplice stringa in un altro oggetto.

Come posso gestire correttamente Gson? La mia classe ha questo descritto come un oggetto List, in modo che funziona per i primi elementi in cui option_value è un array, ma quando diventa una stringa , l'applicazione si blocca e ottengo un'eccezione parse JSON.

Esiste una soluzione alternativa?

UPDATE

Aggiunta la parte rilevante della mia classe come richiesto:

public class Options 
    { 
     String product_option_id; 
     String option_id; 
     String name; 
     String type; 
     String required; 
     List<OptionValue> option_value; 

     // get set stuff here 

     public class OptionValue 
     { 
      String product_option_value_id; 
      String option_value_id; 
      String name; 
      String image; 
      String price; 
      String price_prefix; 

      // get set stuff here 
     } 
    } 
+0

Ciao Asim, puoi mostrare il tuo JSON Parser? – Kansen

+0

Aggiunta la parte pertinente. Sto usando Gson quindi l'analisi è fatta da quella libreria usando la funzione Gson.fromJson (stringa, classe). – Asim

+0

Non è possibile ottenere ciò utilizzando 'GSON.fromJson (String json, Class classOfT)', dovrai definire il tuo adattatore ... diciamo 'StrangeJsonAdapter' estendendo la classe' com.google.gson.TypeAdapter' .. quindi utilizzare il metodo 'StrangeJsonAdapter.fromJson (String json)' per decodificare il tuo json. –

risposta

16

ho una soluzione per voi :) Per questo scopo dobbiamo usare deserializzatore personalizzato. Remake tua classe come questa:

public class Options{ 

    @SerializedName ("product_option_id"); 
    String mProductOptionId; 

    @SerializedName ("option_id"); 
    String mOptionId; 

    @SerializedName ("name"); 
    String mName; 

    @SerializedName ("type"); 
    String mType; 

    @SerializedName ("required"); 
    String mRequired; 

    //don't assign any serialized name, this field will be parsed manually 
    List<OptionValue> mOptionValue; 

    //setter 
    public void setOptionValues(List<OptionValue> optionValues){ 
     mOptionValue = optionValues; 
    } 

    // get set stuff here 
    public class OptionValue 
    { 
     String product_option_value_id; 
     String option_value_id; 
     String name; 
     String image; 
     String price; 
     String price_prefix; 

     // get set stuff here 
    } 

public static class OptionsDeserilizer implements JsonDeserializer<Options> { 

    @Override 
    public Offer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     Options options = new Gson().fromJson(json, Options.class); 
     JsonObject jsonObject = json.getAsJsonObject(); 

     if (jsonObject.has("option_value")) { 
      JsonElement elem = jsonObject.get("option_value"); 
      if (elem != null && !elem.isJsonNull()) { 
       String valuesString = elem.getAsString(); 
       if (!TextUtils.isEmpty(valuesString)){ 
        List<OptionValue> values = new Gson().fromJson(valuesString, new TypeToken<ArrayList<OptionValue>>() {}.getType()); 
        options.setOptionValues(values); 
       } 
      } 
     } 
     return options ; 
    } 
} 
} 

Prima di poter lasciare GSON parse JSON, dobbiamo registrare il nostro deserializzatore personalizzato:

Gson gson = new GsonBuilder()    
      .registerTypeAdapter(Options.class, new Options.OptionsDeserilizer())    
      .create(); 

E ora - basta chiamare:

Options options = gson.fromJson(json, Options.class); 
+1

Ho ottenuto un StackOverflowError a causa della chiamata di deserializzazione ricorsiva su 'Options options = new Gson(). FromJson (json, Options.class);' e due nuove istanze di 'Gson' vengono create nella deserializzazione di un singolo oggetto. Attenzione. – EpicPandaForce

2

Nella mia situazione, il campo con lo stesso nome è "data": {} o "dati": [array_with_real_data]. Quindi il codice dalla risposta accettata deve essere leggermente modificato, come questo:

@Override 
public MyClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
     throws JsonParseException { 
    MyClass bean = new Gson().fromJson(json, MyClass.class); 
    JsonObject jsonObject = json.getAsJsonObject(); 

    if (jsonObject.has("data")) { 
     JsonArray array = jsonObject.getAsJsonArray("data"); 
     if (array != null && !array.isJsonNull()) { 
      List<Data> data = new Gson().fromJson(array, new TypeToken<ArrayList<Data>>() {}.getType()); 
      bean.realData = data; 
     } 
    } 
    return bean ; 
} 

speranza che aiuti.

Problemi correlati