Cómo analizar la matriz JSON con Gson

84

Quiero analizar matrices JSON y usar gson. En primer lugar, puedo registrar la salida JSON, el servidor responde claramente al cliente.

Aquí está mi salida JSON:

 [
      {
           id : '1',
           title: 'sample title',
           ....
      },
      {
           id : '2',
           title: 'sample title',
           ....
     },
      ...
 ]

Probé esta estructura para analizar. Una clase, que depende de JSONArray único arrayy ArrayListpara todos.

 public class PostEntity {

      private ArrayList<Post> postList = new ArrayList<Post>();

      public List<Post> getPostList() { 
           return postList; 
      }

      public void setPostList(List<Post> postList) { 
           this.postList = (ArrayList<Post>)postList; 
      } 
 }

Post clase:

 public class Post {

      private String id;
      private String title;

      /* getters & setters */
 }

Cuando trato de usar gson sin error, sin advertencia y sin registro:

 GsonBuilder gsonb = new GsonBuilder();
 Gson gson = gsonb.create();

 PostEntity postEnt;
 JSONObject jsonObj = new JSONObject(jsonOutput);
 postEnt = gson.fromJson(jsonObj.toString(), PostEntity.class);

 Log.d("postLog", postEnt.getPostList().get(0).getId());

¿Qué pasa, cómo puedo solucionarlo?

Ogulcan Orhan
fuente

Respuestas:

248

Puede analizar JSONArraydirectamente, no es necesario que envuelva su Postclase PostEntityuna vez más y tampoco necesita una nueva JSONObject().toString():

Gson gson = new Gson();
String jsonOutput = "Your JSON String";
Type listType = new TypeToken<List<Post>>(){}.getType();
List<Post> posts = gson.fromJson(jsonOutput, listType);

Espero que ayude.

yorkw
fuente
Eliminé la clase PostEntity y probé tu fragmento. Todavía no hay cambios. Gracias.
Ogulcan Orhan
Finalmente funcionó de manera correcta y eficiente. Muchas gracias de nuevo.
Ogulcan Orhan
Hola, cómo analizar datos de matriz json anidados como este ... [{"firstName": "Bidhan", "lastName": "Chatterjee"}, [{"type": "personal", "number": "09832209761" }, {"type": "fax", "number": "91-342-2567692"}]]
KK_07k11A0585
¿Existe algún beneficio al usar TypeToken? Según mis pruebas, gson parece manejar un campo List <Object> sin usar TypeToken.
greg7gkb
Esto es realmente útil para mí
bhavesh kaila
6

Estaba buscando una forma de analizar matrices de objetos de una manera más genérica; aquí está mi contribución:

CollectionDeserializer.java:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import com.google.gson.Gson;
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 CollectionDeserializer implements JsonDeserializer<Collection<?>> {

    @Override
    public Collection<?> deserialize(JsonElement json, Type typeOfT,
            JsonDeserializationContext context) throws JsonParseException {
        Type realType = ((ParameterizedType)typeOfT).getActualTypeArguments()[0];

        return parseAsArrayList(json, realType);
    }

    /**
     * @param serializedData
     * @param type
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> ArrayList<T> parseAsArrayList(JsonElement json, T type) {
        ArrayList<T> newArray = new ArrayList<T>();
        Gson gson = new Gson();

        JsonArray array= json.getAsJsonArray();
        Iterator<JsonElement> iterator = array.iterator();

        while(iterator.hasNext()){
            JsonElement json2 = (JsonElement)iterator.next();
            T object = (T) gson.fromJson(json2, (Class<?>)type);
            newArray.add(object);
        }

        return newArray;
    }

}

JSONParsingTest.java:

public class JSONParsingTest {

    List<World> worlds;

    @Test
    public void grantThatDeserializerWorksAndParseObjectArrays(){

        String worldAsString = "{\"worlds\": [" +
            "{\"name\":\"name1\",\"id\":1}," +
            "{\"name\":\"name2\",\"id\":2}," +
            "{\"name\":\"name3\",\"id\":3}" +
        "]}";

        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(Collection.class, new CollectionDeserializer());
        Gson gson = builder.create();
        Object decoded = gson.fromJson((String)worldAsString, JSONParsingTest.class);

        assertNotNull(decoded);
        assertTrue(JSONParsingTest.class.isInstance(decoded));

        JSONParsingTest decodedObject = (JSONParsingTest)decoded;
        assertEquals(3, decodedObject.worlds.size());
        assertEquals((Long)2L, decodedObject.worlds.get(1).getId());
    }
}

World.java:

public class World {
    private String name;
    private Long id;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}
Miere
fuente
@Miere No entiendo cómo se convierte esto de JsonArray a List <World>
ARK
Básicamente, utiliza CollectionDeserializer para cada colección que se encuentra durante el proceso de deserialización de GSON. CollectionDeserializer a su vez, infiere a través del parámetro genérico de la colección qué clase representa el almacén de objetos en la colección que debe deserializar. Espero que esto haya respondido a su pregunta. Si aún tiene dudas, por favor contácteme al [miere00 at gmail.com].
Miere
Hola @ Miere, esta solución no maneja la pregunta original. Su JSONParsingTest es un objeto con una matriz dentro. ¿Cómo usa su CollectionDeserializer para analizar solo una matriz, no una matriz envuelta en un objeto?
zkon
5

Para conversar en Object Array

Gson gson=new Gson();
ElementType [] refVar=gson.fromJson(jsonString,ElementType[].class);

Para convertir como tipo de publicación

Gson gson=new Gson();
Post [] refVar=gson.fromJson(jsonString,Post[].class);

Para leerlo como Lista de objetos, se puede usar TypeToken

List<Post> posts=(List<Post>)gson.fromJson(jsonString, 
                     new TypeToken<List<Post>>(){}.getType());
xrcwrn
fuente
¿Qué tal como ArrayList <Post>?
Gumuruh
3
Type listType = new TypeToken<List<Post>>() {}.getType();
List<Post> posts = new Gson().fromJson(jsonOutput.toString(), listType);
Salman Khan
fuente
6
Si bien esto puede responder a la pregunta, no proporciona ningún contexto para explicar cómo o por qué. Considere agregar una oración o dos para explicar su respuesta.
brandonscript
3

Algunas de las respuestas de esta publicación son válidas, pero usando TypeToken, la biblioteca Gson genera objetos de árbol con tipos irreales para su aplicación.

Para conseguirlo tuve que leer la matriz y convertir uno por uno los objetos dentro de la matriz. Por supuesto, este método no es el más rápido y no recomiendo usarlo si la matriz es demasiado grande, pero funcionó para mí.

Es necesario incluir la biblioteca Json en el proyecto. Si está desarrollando en Android, se incluye:

/**
 * Convert JSON string to a list of objects
 * @param sJson String sJson to be converted
 * @param tClass Class
 * @return List<T> list of objects generated or null if there was an error
 */
public static <T> List<T> convertFromJsonArray(String sJson, Class<T> tClass){

    try{
        Gson gson = new Gson();
        List<T> listObjects = new ArrayList<>();

        //read each object of array with Json library
        JSONArray jsonArray = new JSONArray(sJson);
        for(int i=0; i<jsonArray.length(); i++){

            //get the object
            JSONObject jsonObject = jsonArray.getJSONObject(i);

            //get string of object from Json library to convert it to real object with Gson library
            listObjects.add(gson.fromJson(jsonObject.toString(), tClass));
        }

        //return list with all generated objects
        return listObjects;

    }catch(Exception e){
        e.printStackTrace();
    }

    //error: return null
    return null;
}
JSR - Silicornio
fuente
3
[
      {
           id : '1',
           title: 'sample title',
           ....
      },
      {
           id : '2',
           title: 'sample title',
           ....
     },
      ...
 ]

Verifique el código fácil para esta salida

 Gson gson=new GsonBuilder().create();
                List<Post> list= Arrays.asList(gson.fromJson(yourResponse.toString,Post[].class));
Prabh profundo
fuente
1

Puede hacer esto fácilmente en Kotlin usando el siguiente código:

val fileData = "your_json_string"
val gson = GsonBuilder().create()
val packagesArray = gson.fromJson(fileData , Array<YourClass>::class.java).toList()

Básicamente, sólo es necesario para proporcionar un Arrayde YourClasslos objetos.

xarlymg89
fuente
¿Por qué utiliza PrettyPrinting?
Antroid
@antroid Olvidé eliminarlo ^^
xarlymg89
0

puede obtener el valor de Lista sin usar el objeto Tipo .

EvalClassName[] evalClassName;
ArrayList<EvalClassName> list;
evalClassName= new Gson().fromJson(JSONArrayValue.toString(),EvalClassName[].class);
list = new ArrayList<>(Arrays.asList(evalClassName));

Lo he probado y está funcionando.

Sumit Kumar
fuente
0

en Kotlin :

val jsonArrayString = "['A','B','C']"

val gson = Gson()

val listType: Type = object : TypeToken<List<String?>?>() {}.getType()

val stringList : List<String> = gson.fromJson(
                            jsonArrayString,
                            listType)
Adnan Abdollah Zaki
fuente