Gson Parse Json con matriz con diferentes tipos de objetos

¿Cómo puedo analizar este JSON usando Gson? Tengo una matriz con múltiples tipos de objetos y no sé qué tipo de objeto necesito crear para guardar esta estructura. No puedo cambiar el mensaje json (no controlo el servidor).

La única clase que funcionaba (clase de) era esta

public class Response { private List<Object> tr; private int results; (...) } 

Mensaje JSON (Observe la matriz con varios tipos de objetos.)

 { "tr": [ { "a": { "userId": "112" } }, { "b": { "userId": "123", "address":"street dummy" } }, { "a": { "userId": "154" } } ], "results":3 } 

La Guía del usuario de Gson explícitamente cubre esto:

https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Collection-with-Objects-of-Arbitrary-Types

Tiene un objeto con un campo tr que es un array que contiene tipos arbitrarios.

La guía de usuario explica que no se puede deserializar directamente dicha estructura y se recomienda:

Utilice el API de analizador de Gson (analizador de flujo continuo de bajo nivel o el analizador de DOM JsonParser) para analizar los elementos de la matriz y, a continuación, utilice Gson.fromJson () en cada uno de los elementos de la matriz. Este es el enfoque preferido.

En su caso … realmente dependería de qué objetos eran posibles en esa matriz. Si todos van a tener ese mismo objeto interior que usted querría hacer algo como …

 List<MyUserPojo> list = new ArrayList<MyUserPojo>(); JsonArray array = parser.parse(json).getAsJsonObject().getAsJsonArray("tr"); for (JsonElement je : array) { Set<Map.Entry<String,JsonElement>> set = je.getAsObject().entrySet(); JsonElement je2 = set.iterator().next().getValue(); MyUserPojo mup = new Gson().fromJson(je2, MyUserPojo.class); list.add(mup); } 

Y por supuesto, esto tendría que estar dentro de un deserializador personalizado para su objeto real que tendría los campos tr y results .

 class MyPojo { List<MyUserPojo> userList; int results; } class MyUserPojo { String userId; String address; } class MyDeserializer implements JsonDeserializer<MyPojo> { @Override public MyPojo deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException { List<MyUserPojo> list = new ArrayList<MyUserPojo>(); JsonArray array = je.getAsJsonObject().getAsJsonArray("tr"); for (JsonElement je2 : array) { Set<Map.Entry<String,JsonElement>> set = je2.getAsObject().entrySet(); JsonElement je3 = set.iterator().next().getValue(); MyUserPojo mup = new Gson().fromJson(je3, MyUserPojo.class); list.add(mup); } MyPojo mp = new MyPojo(); mp.tr = list; mp.results = je.getAsObject().getAsJsonPrimitive("results").getAsInt(); return mp; } } 

Ahora ya está todo – puede usar ese deserializador y crear su objeto:

 Gson gson = new GsonBuilder() .registerTypeAdapter(MyPojo.class, new MyDeserializer()) .build(); MyPojo mp = gson.fromJson(json, MyPojo.class); 

Si el a , b etc son importantes … bueno, tendrás que averiguarlo. Pero lo anterior debería ayudarle a entender lo que va a necesitar para manejar su estructura JSON.

Para el bien de la integridad, la única manera de "hacky" alrededor de esto es si hay un número bastante limitado de esos tipos y el objeto interno también es bastante limitado en términos de sus campos. Puede crear un POJO que abarque todas las posibilidades:

 class MyPojo { MySecondPojo a; MySecondPojo b; ... MySecondPojo f; } class MySecondPojo { String userId; String address; ... String someOtherField; } 

Cuando Gson deserializa JSON, establecerá los campos que faltan en su POJO (s) a null . Ahora puede tener una List o una matriz de estos en su POJO. Una vez más y para enfatizar, esto es realmente muy hacky y la forma incorrecta de hacerlo , pero pensé que iba a explicar lo que sería necesario para analizar directamente esa matriz.

Escojo algo de cada respuesta y lo hice de esta manera:

ResponseObject

 public class Response { private List<Users> tr; private int results; (...) } 

Usuario Generico

 public class User { public static final int TYPE_USER_A =0; public static final int TYPE_USER_B =1; private String userId; private int type; (...) } 

UN

 public class a extends User { private Strngt location; (...) } 

segundo

 public class b extends User { private String adress; (...) } 

Método de análisis

 private Response buildResponseObject(String response) { Response tls = new Response(); List<Users> users = new ArrayList<users>(); User u; try { JSONObject object = new JSONObject(response); tls.setResults(object.getInt("results")); JSONArray array = object.getJSONArray("tr"); for (int i = 0; i < array.length(); i++) { JSONObject trs = array.getJSONObject(i); if (trs.has("a")) { String json = trns.getString("a"); A a = new Gson().fromJson(json,A.class); a.setType(User.TYPE_USER_A); users.add(a); } else if (trs.has("b")) { String json = trs.getString("b"); B b= new Gson().fromJson(json,B.class); B.setType(User.TYPE_USER_B); users.add(b); } } tls.setUsers(users); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } return tls; } 

Esto no es tan elegante como yo quería y mezcla JsonObjects nativo con métodos de Gson, pero funciona para mí.

Pruebe este código aquí:

 public class Address { public String userId; public String address; // ... } public class Response { private HashMap<String, Address> tr; private int results; // ... } 

Uso:

 String json = "{\n \"tr\":\n {\n \"a\": {\n \"userId\": \"112\"\n },\n \"b\": {\n \"userId\": \"123\",\n \"address\":\"street dummy\"\n },\n \"c\": {\n \"userId\": \"154\"\n }\n },\n \"results\":3\n}"; Response users = new Gson().fromJson(json, Response.class); 

Como puede ver necesito modificar la estructura:

 { "tr": { "a": { "userId": "112" }, "b": { "userId": "123", "address":"street dummy" }, "c": { "userId": "154" } }, "results":3 } 

Pero desafortunadamente no lo consigo manejado permitir múltiples llaves. Ahora mismo no tengo ni idea de cómo arreglar esto.

Creo que este vínculo podría ayudarte: https://sites.google.com/site/gson/gson-user-guide#TOC-Collections-Examples

Básicamente, crear una clase para su "objeto" (tipo de usuario, supongo), y luego usar el código de deserialización de Gson, así:

 Type collectionType = new TypeToken<Collection<User>>(){}.getType(); Collection<User> users= gson.fromJson(json, collectionType); 

Puede crear clases java correspondientes para los objetos json. El entero, los valores de cadena se pueden mapear como es. Json se puede analizar así:

 Gson gson = new GsonBuilder().create(); Response r = gson.fromJson(jsonString, Response.class); 

Aquí hay un ejemplo: http://rowsandcolumns.blogspot.com/2013/02/url-encode-http-get-solr-request-and.html

  • Archivo o base de datos? - Mejores prácticas para guardar objetos en dispositivos Android
  • Cómo analizar la matriz json anidado en android utilizando volley biblioteca
  • ¿Cómo puedo consultar de forma segura (indirecta) una base de datos postgresql en android?
  • Múltiples elementos seleccionados RecyclerView in Activity.java
  • Cómo analizar un archivo JSON grande en android
  • ¿Por qué no hay un método remove (int position) en JSONArray de Android?
  • Excepción no manipulada org.json.jsonexception
  • Pojo analiza gson con nombres de java no válidos
  • Android no procesar objeto JSON
  • Retrofit: Se esperaba BEGIN_OBJECT pero era BEGIN_ARRAY
  • Respuesta de JSON de Django en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.