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
- Json a clases de datos kotlin
- Pruebe la carpeta de recursos con Robolectric y Gradle
- Cómo ordenar / organizar las claves de objeto JSON en android?
- ¿Conversión de json string a objeto java?
- Cómo convertir HttpEntity en JSON?
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 }
- Google Place API - autocompletar - cómo obtener código postal?
- Android paginada lista sin fin no funciona
- Com.google.gson.JsonSyntaxException al intentar analizar Date / Time en json
- Obtener claves de array json en android
- Firebase "mientras se deserializaba, pero obtuvo una clase java.util.ArrayList"
- Android JSON a PHP Server y volver
- Crear archivo JSON en línea y obtener URL
- Android JSON Jackson Tutorial
La Guía del usuario de Gson explícitamente cubre esto:
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
- ¿Cómo implementar la base de datos en la aplicación PhoneGap?
- Problema con la conexión Bluetooth de Android