2011-03-21 30 views
11

Deseo utilizar GSON para analizar el siguiente JSON:GSON para analizar matriz con múltiples tipos

[ 
    [ 
     "hello", 
     1, 
     [2] 
    ], 
    [ 
     "world", 
     3, 
     [2] 
    ] 
] 

Entonces, eso es 1 matriz, que contiene 2 arrays. Las 2 matrices internas son en sí mismas matrices, compuestas por String, int, tipos de matriz.

No estoy seguro de cómo puedo usar clases de Java para modelar la matriz que tiene 3 tipos diferentes (String, int, array). Comienzo con:

// String json just contains the aforementioned json string. 

ArrayList<ArrayList<XXX>> data = new ArrayList<ArrayList<XXX>>(); 

Type arrayListType = new TypeToken<ArrayList<ArrayList<XXX>>>(){}.getType(); 

data = gson.fromJson(json, arrayListType); 

Pero, ¿qué debería ser donde están los 'XXX'? Creo que debería ser una matriz, pero debería ser una matriz con 3 tipos de datos diferentes. Entonces, ¿cómo puedo usar Java para modelar esto?

¿Puede alguna ayuda? Gracias.

+0

su JSON es _wrong_. – Nishant

+1

El código es exactamente como lo recibo del servidor ... lamentablemente no puedo cambiar los datos que recibo. Por supuesto, eso no hace que los datos JSON sean correctos. : P – Fofx

+0

Posible duplicado de [matriz JSON deserializar Gson con múltiples tipos de objetos] (https://stackoverflow.com/questions/36780871/gson-deserialize-json-array-with-multiple-object-types) – ed22

Respuesta

0

En primer lugar, creo que puede estar equivocado en su ejemplo anterior. Una matriz que consta de tres diferentes es un enfoque muy inusual, por decir lo menos. Probablemente su estructura json es una matriz que contiene tuplas. Estas tuplas incluyen una matriz.

térmica:

[ 
{ 
    "hello", 
    1, 
    [2] 
}, 
{ 
    "world", 
    3, 
    [2] 
} 
] 

XXX debe ser un objeto que contiene:

A String

Un int (o entero)

una matriz de (supongo) ints.

Luego se hace una matriz de estos objetos y se analiza el json.

Sin embargo, su JSON parece muy mal formados, ya que todos los miembros deben ser nombrados, como

[ 
{ 
    "str":"hello", 
    "intVal":1, 
    "intArr":[2] 
}, 
{ 
    "str":"world", 
    "intVal":3, 
    "intArr":[2] 
} 
] 

Si, por el contrario, el JSON realmente se ve la forma en que lo describes, que tendría que hacer arrays de Object, simple y llanamente, y luego echarlos cuando los lea desde su estructura de datos.

+0

Este es exactamente mi pensando demasiado ... que si el JSON estaba en el formato: { "str": "hola", "intval": 1, "intArr": [2] }, Entonces podría simplemente crear mi propia clase, que modeló esta información. Desafortunadamente los datos realmente son como los que publiqué ... de ahí mi problema y esta publicación :) Voy a intentar su sugerencia y ver si funciona. Gracias por su respuesta. – Fofx

+0

OK, no estoy seguro de que este enfoque de conversión funcionaría. ¿Está sugiriendo que haga algo como: 'ArrayList > data = new ArrayList >(); \t Escriba arrayListType = new TypeToken >>() {}. GetType(); \t data = gson.fromJson (json, arrayListType); ' Entiendo cómo puede funcionar esto para almacenar un String o int, pero el tercer elemento de la matriz es una matriz, y si esta matriz contiene un objeto JSON {}, entonces ¿Cómo podría modelar esto? – Fofx

+0

Recibo el siguiente error: 'com.google.gson.JsonParseException: la información del tipo no está disponible, y el destino no es un primitivo: [2]' Tiene un problema con el 3er artículo ... el intArr – Fofx

13

Gson tiene un manejo especial para deserializar algunas matrices de un solo componente en un tipo que no sea de matriz. Por ejemplo, int data = gson.fromJson("[3]", int.class); asignaría el valor int 3 a los datos.

Por supuesto, no se requiere deserializar una matriz de componente único en un tipo que no sea de matriz. Por ejemplo, el ejemplo anterior podría deserializarse como int[] data = gson.fromJson("[3]", int[].class);.

Gson también a menudo deserializará un valor que no sea de Cadena en una Cadena, cuando se le solicite. Aplicando esto al primer ejemplo, String data = gson.fromJson("[3]", String.class); funciona igual de bien.

Tenga en cuenta que no funciona decirle a Gson que deserialice el primer ejemplo como tipo Object. Object data = gson.fromJson("[3]", Object.class); da como resultado una excepción de análisis quejándose de que [3] no es primitivo.

Aplicado al ejemplo en la pregunta original anterior, si es aceptable tratar todos los valores como cadenas, entonces la deserialización se vuelve simple.

// output: 
// hello 1 2 
// world 3 2 

public class Foo 
{ 
    static String jsonInput = 
    "[" + 
     "[\"hello\",1,[2]]," + 
     "[\"world\",3,[2]]" + 
    "]"; 

    public static void main(String[] args) 
    { 
    Gson gson = new Gson(); 
    String[][] data = gson.fromJson(jsonInput, String[][].class); 
    for (String[] data2 : data) 
    { 
     for (String data3 : data2) 
     { 
     System.out.print(data3); 
     System.out.print(" "); 
     } 
     System.out.println(); 
    } 
    } 
} 

Por desgracia, con Gson no he sido capaz de averiguar un enfoque deserialización simple que permitiría la "mejor" la unión a tipos más específicos y mixtos en una matriz, ya que Java no proporciona una sintaxis para definir una matriz de tipo mixto. Por ejemplo, el tipo preferido de la colección en la pregunta original podría ser List<List<String, int, List<int>>>, pero no es posible definirlo en Java. Por lo tanto, debe contentarse con List<List<String>> (or String[][]), o recurrir a un enfoque con más análisis "manual".

(Sí, Java permite una declaración de tipo de List<List<Object>>, pero Object no es un tipo lo suficientemente específico para deserializar significativa a. También, como se ha discutido, tratando de deserializar [3] para objetos como resultado una excepción de análisis sintáctico.)


Pequeña actualización: Recientemente tuve que deserializar algunos JSON descuidados que incluían una estructura no muy diferente de la de la pregunta original. Terminé usando un deserializador personalizado para crear un objeto a partir de la desordenada matriz JSON. Similar al siguiente ejemplo.

// output: 
// [{MyThreeThings: first=hello, second=1, third=[2]}, 
// {MyThreeThings: first=world, second=3, third=[4, 5]}] 

import java.lang.reflect.Type; 
import java.util.Arrays; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.JsonArray; 
import com.google.gson.JsonDeserializationContext; 
import com.google.gson.JsonDeserializer; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonParseException; 

public class FooToo 
{ 
    static String jsonInput = 
     "[" + 
      "[\"hello\",1,[2]]," + 
      "[\"world\",3,[4,5]]" + 
     "]"; 

    public static void main(String[] args) 
    { 
    GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(MyThreeThings.class, new MyThreeThingsDeserializer()); 
    Gson gson = gsonBuilder.create(); 
    MyThreeThings[] things = gson.fromJson(jsonInput, MyThreeThings[].class); 
    System.out.println(Arrays.toString(things)); 
    } 
} 

class MyThreeThings 
{ 
    String first; 
    int second; 
    int[] third; 

    MyThreeThings(String first, int second, int[] third) 
    { 
    this.first = first; 
    this.second = second; 
    this.third = third; 
    } 

    @Override 
    public String toString() 
    { 
    return String.format(
     "{MyThreeThings: first=%s, second=%d, third=%s}", 
     first, second, Arrays.toString(third)); 
    } 
} 

class MyThreeThingsDeserializer implements JsonDeserializer<MyThreeThings> 
{ 
    @Override 
    public MyThreeThings deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
     throws JsonParseException 
    { 
    JsonArray jsonArray = json.getAsJsonArray(); 
    String first = jsonArray.get(0).getAsString(); 
    int second = jsonArray.get(1).getAsInt(); 
    JsonArray jsonArray2 = jsonArray.get(2).getAsJsonArray(); 
    int length = jsonArray2.size(); 
    int[] third = new int[length]; 
    for (int i = 0; i < length; i++) 
    { 
     int n = jsonArray2.get(i).getAsInt(); 
     third[i] = n; 
    } 
    return new MyThreeThings(first, second, third); 
    } 
} 

La guía del usuario Gson hace deserialización de colecciones de tipos mixtos manejo de la cubierta con un ejemplo similar como esto en the "Serializing and Deserializing Collection with Objects of Arbitrary Types" section.

Cuestiones relacionadas