tutorial - leer json en java
¿Por qué Gson de Json lanzar una JsonSyntaxException: Se esperaba algún tipo, pero era algún otro tipo? (2)
class Pojo {
NestedPojo nestedPojo;
}
en su json usted tiene un arsenal de nestedPojo así que usted cambia el código
NestedPojo[] nestedPojo;
o cambiar la cadena json
String json = "{/"nestedPojo/":{/"name/":null, /"value/":42}}";
(Esta publicación está destinada a ser una pregunta canónica con una respuesta de ejemplo proporcionada a continuación.)
Estoy tratando de deserializar algún contenido de JSON en un tipo POJO personalizado con Gson#fromJson(String, Class)
.
Este pedazo de código
import com.google.gson.Gson;
public class Sample {
public static void main(String[] args) {
String json = "{/"nestedPojo/":[{/"name/":null, /"value/":42}]}";
Gson gson = new Gson();
gson.fromJson(json, Pojo.class);
}
}
class Pojo {
NestedPojo nestedPojo;
}
class NestedPojo {
String name;
int value;
}
lanza la siguiente excepción
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:200)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:103)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
at com.google.gson.Gson.fromJson(Gson.java:810)
at com.google.gson.Gson.fromJson(Gson.java:775)
at com.google.gson.Gson.fromJson(Gson.java:724)
at com.google.gson.Gson.fromJson(Gson.java:696)
at com.example.Sample.main(Sample.java:23)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:387)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:189)
... 7 more
¿Por qué Gson no puede convertir correctamente mi texto JSON a mi tipo POJO?
A medida que el mensaje de excepción indica
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
mientras que la deserialización, Gson esperaba un objeto JSON, pero encontró una matriz JSON. Puesto que no podía convertir de uno a otro, lanzó esta excepción.
El formato JSON se describe aquí . En resumen, define los siguientes tipos: objetos, matrices, cadenas, números, null
y los valores booleanos true
y false
.
En Gson (y la mayoría de los analizadores JSON), existen las siguientes asignaciones: una cadena JSON se correlaciona con una String
Java; un número JSON se asigna a un tipo de Number
Java; una matriz JSON se correlaciona con un tipo de Collection
o un tipo de matriz; un objeto JSON se asigna a un tipo de Map
Java o, por lo general, un tipo de POJO personalizado (no mencionado anteriormente); mapas null
a null
de Java y los valores booleanos asignan a true
y false
Java.
Gson itera a través del contenido JSON que proporciona y trata de deserializarlo al tipo correspondiente que ha solicitado. Si el contenido no coincide o no puede convertirse al tipo esperado, lanzará una excepción correspondiente.
En su caso, usted proporcionó el siguiente JSON
{
"nestedPojo": [
{
"name": null,
"value": 42
}
]
}
En la raíz, se trata de un objeto JSON que contiene un miembro denominado nestedPojo
que es una matriz JSON. Ese conjunto JSON contiene un solo elemento, otro objeto JSON con dos miembros. Teniendo en cuenta las asignaciones definidas anteriormente, se espera que este JSON para asignar a un objeto Java que tiene un campo llamado nestedPojo
de algún tipo de Collection
o matriz, donde ese tipo define dos campos denominados name
y value
, respectivamente.
Sin embargo, usted ha definido su tipo Pojo
como tener un campo
NestedPojo nestedPojo;
que no es ni un tipo de matriz, ni un tipo de Collection
. Gson no puede deserializar el JSON correspondiente para este campo.
En su lugar, tiene 3 opciones:
Cambie su JSON para que coincida con el tipo esperado
{ "nestedPojo": { "name": null, "value": 42 } }
Cambie su tipo
Pojo
para esperar unaCollection
o tipo de matrizList<NestedPojo> nestedPojo; // consider changing the name and using @SerializedName NestedPojo[] nestedPojo;
Escriba y registre un deserializador personalizado para
NestedPojo
con sus propias reglas de análisis. Por ejemploclass Custom implements JsonDeserializer<NestedPojo> { @Override public NestedPojo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { NestedPojo nestedPojo = new NestedPojo(); JsonArray jsonArray = json.getAsJsonArray(); if (jsonArray.size() != 1) { throw new IllegalStateException("unexpected json"); } JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); // get only element JsonElement jsonElement = jsonObject.get("name"); if (!jsonElement.isJsonNull()) { nestedPojo.name = jsonElement.getAsString(); } nestedPojo.value = jsonObject.get("value").getAsInt(); return nestedPojo; } } Gson gson = new GsonBuilder().registerTypeAdapter(NestedPojo.class, new Custom()).create();