Come decodificare JSON con campo sconosciuto usando Gson?

Ho JSON simile a questo:

{ "unknown_field": { "field1": "str", "field2": "str", "field3": "str", "field4": "str", "field5": "str" }, ...... } 

Ho creato delle classi per mappare questo json

 public class MyModel implements Serializable { private int id; private HashMap models; // getters and setter for id and models here } 

e la class Model1 è una class semplice solo con campi String.

Ma non funziona.

Modifica : il formato JSON ha il seguente aspetto:

 { "1145": { "cities_id": "1145", "city": "Nawanshahr", "city_path": "nawanshahr", "region_id": "53", "region_district_id": "381", "country_id": "0", "million": "0", "population": null, "region_name": "Punjab" }, "1148": { "cities_id": "1148", "city": "Nimbahera", "city_path": "nimbahera", "region_id": "54", "region_district_id": "528", "country_id": "0", "million": "0", "population": null, "region_name": "Rajasthan" }, ... } 

(Dopo che OP ha commentato che in effetti il JSON sembra così , ho completamente aggiornato la risposta).

Soluzione per Gson 2.0+

Ho appena saputo che con le nuove versioni di Gson questo è estremamente semplice:

 GsonBuilder builder = new GsonBuilder(); Object o = builder.create().fromJson(json, Object.class); 

L’object creato è una mappa (com.google.gson.internal.LinkedTreeMap) e, se lo stampi, assomiglia a questo:

 {1145={cities_id=1145, city=Nawanshahr, city_path=nawanshahr, region_id=53, region_district_id=381, country_id=0, million=0, population=null, region_name=Punjab}, 1148={cities_id=1148, city=Nimbahera, city_path=nimbahera, region_id=54, region_district_id=528, country_id=0, million=0, population=null, region_name=Rajasthan} ... 

Soluzione utilizzando un deserializzatore personalizzato

( NB : Si scopre che non si è realmente un deserializzatore personalizzato a meno che non si sia bloccati con versioni precedenti alla 2.0 di Gson. Tuttavia, è ancora utile sapere come procedere alla deserializzazione (e serializzazione) su Gson , e potrebbe spesso essere l’approccio migliore, a seconda di come si desidera utilizzare i dati analizzati.)

Quindi abbiamo effettivamente a che fare con nomi di campi casuali / variabili. (Naturalmente, questo formato JSON non è molto buono, questo tipo di dati dovrebbe essere all’interno di un array JSON , nel qual caso potrebbe essere facilmente letto in una lista. Oh beh, possiamo ancora analizzarlo.)

Innanzitutto, ecco come modellerei i dati JSON negli oggetti Java:

 // info for individual city public class City { String citiesId; String city; String regionName; // and so on } // top-level object, containing info for lots of cities public class CityList { List cities; public CityList(List cities) { this.cities = cities; } } 

Quindi, l’analisi. Un modo per gestire questo tipo di JSON è creare un deserializzatore personalizzato per l’object di livello superiore (CityList).

Qualcosa come questo:

 public class CityListDeserializer implements JsonDeserializer { @Override public CityList deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = element.getAsJsonObject(); List cities = new ArrayList(); for (Map.Entry entry : jsonObject.entrySet()) { // For individual City objects, we can use default deserialisation: City city = context.deserialize(entry.getValue(), City.class); cities.add(city); } return new CityList(cities); } } 

Un punto chiave da notare è la chiamata a jsonObject.entrySet() che ritriggers tutti i campi di livello superiore (con nomi come “1145”, “1148”, ecc.). Questa risposta di Stack Overflow mi ha aiutato a risolvere questo problema.

Completa il codice di analisi qui sotto. Si noti che è necessario utilizzare registerTypeAdapter() per registrare il serializzatore personalizzato.

 GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(CityList.class, new CityListDeserializer()); Gson gson = builder.setFieldNamingPolicy(LOWER_CASE_WITH_UNDERSCORES).create(); CityList list = gson.fromJson(json, CityList.class); 

(Ecco un esempio completo e eseguibile che ho usato per il test. Oltre a Gson, utilizza la libreria Guava.)