¿Cómo decodificar JSON con un campo desconocido usando Gson?

Tengo JSON similar a esto:

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

Creé clases para mapear este json

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

y la clase Model1 es una clase simple solo con campos String.

Pero no funciona.

Editar : el formato JSON se ve así:

 { "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" }, ... } 

(Después de que OP comentó que, de hecho, el JSON se ve así , actualicé completamente la respuesta).

Solución para Gson 2.0+

Acabo de aprender que con las versiones más nuevas de Gson esto es extremadamente simple:

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

El objeto creado es un Mapa (com.google.gson.internal.LinkedTreeMap), y si lo imprime, se ve así:

 {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} ... 

Solución usando un deserializador personalizado

( NB : Resulta que realmente no es un deserializador personalizado a menos que esté atascado con las versiones anteriores a 2.0 de Gson. Sin embargo, es útil saber cómo hacer la deserialización personalizada (y la serialización) en Gson , y a menudo puede ser el mejor enfoque, dependiendo de cómo quiera usar los datos analizados.)

Así que estamos tratando con nombres de campos aleatorios / variables. (Por supuesto, este formato JSON no es muy bueno, este tipo de datos debe estar dentro de una matriz JSON , en cuyo caso podría leerse fácilmente en una lista. Bueno, todavía podemos analizar esto).

En primer lugar, así es como modelaría los datos JSON en objetos 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; } } 

Entonces, el análisis. Una forma de lidiar con este tipo de JSON es crear un deserializador personalizado para el objeto de nivel superior (CityList).

Algo como esto:

 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 clave a tener en cuenta es la llamada a jsonObject.entrySet() que retoma todos los campos de nivel superior (con nombres como “1145”, “1148”, etc.). Esta respuesta Stack Overflow me ayudó a resolver esto.

Complete el código de análisis a continuación. Tenga en cuenta que necesita usar registerTypeAdapter() para registrar el serializador personalizado.

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

(Aquí hay un ejemplo completo y ejecutable que utilicé para las pruebas. Además de Gson, usa la biblioteca de Guava).