JsonMappingException: fuera del token de START_ARRAY

112

Dado el siguiente archivo .json:

[
    {
        "name" : "New York",
        "number" : "732921",
        "center" : [
                "latitude" : 38.895111, 
                "longitude" : -77.036667
            ]
    },
    {
        "name" : "San Francisco",
        "number" : "298732",
        "center" : [
                "latitude" : 37.783333, 
                "longitude" : -122.416667
            ]
    }
]

Preparé dos clases para representar los datos contenidos:

public class Location {
    public String name;
    public int number;
    public GeoPoint center;
}

...

public class GeoPoint {
    public double latitude;
    public double longitude;
}

Para analizar el contenido del archivo .json, utilizo Jackson 2.2.xy preparé el siguiente método:

public static List<Location> getLocations(InputStream inputStream) {
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        TypeFactory typeFactory = objectMapper.getTypeFactory();
        CollectionType collectionType = typeFactory.constructCollectionType(
                                            List.class, Location.class);
        return objectMapper.readValue(inputStream, collectionType);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Siempre que omita la centerpropiedad, se puede analizar todo el contenido. Sin embargo, cuando trato de analizar las coordenadas geográficas, termino con el siguiente mensaje de error:

com.fasterxml.jackson.databind.JsonMappingException: no se puede deserializar la instancia de
com.example.GeoPoint fuera del token START_ARRAY en [Fuente: android.content.res.AssetManager$AssetInputStream@416a5850; línea: 5, columna: 25]
(a través de la cadena de referencia: com.example.Location ["center"])

JJD
fuente
por qué está usando jackson si simplemente puede analizarlo con json parser
Shashank Agarwal
4
Su cadena JSON está mal formada, el tipo de centeres una matriz de objetos no válidos. Intente reemplazar [y ]con {y }en la cadena JSON alrededor longitudey latitudeasí serán objetos.
Katona
1
@Katona Gracias. ¿Puede convertir su comentario en una respuesta para que pueda cerrar la pregunta?
JJD

Respuestas:

75

Su cadena JSON está mal formada: el tipo de centeres una matriz de objetos no válidos. Reemplace [y ]con {y }en la cadena JSON alrededor longitudey latitudeasí serán objetos:

[
    {
        "name" : "New York",
        "number" : "732921",
        "center" : {
                "latitude" : 38.895111, 
                "longitude" : -77.036667
            }
    },
    {
        "name" : "San Francisco",
        "number" : "298732",
        "center" : {
                "latitude" : 37.783333, 
                "longitude" : -122.416667
            }
    }
]
Katona
fuente
1
El mismo problema que tuve, pero una locura ya que en jackson 2.6.3v había un error loco totalmente diferente, y con 2.9.8v todo funcionó. Maldita sea, estos errores de serialización son tan molestos.
brebDev
114

JsonMappingException: out of START_ARRAY tokenLa excepción es lanzada por el mapeador de objetos de Jackson, ya que espera un Object {}mientras que encontró una Array [{}]en respuesta.

Esto se puede resolver reemplazando Objectcon Object[]en el argumento de geForObject("url",Object[].class). Referencias:

  1. Ref.1
  2. Ref.2
  3. Ref.3
Abhijeet
fuente
9

Resolví este problema para verificar el json de JSONLint.com y luego corregirlo. Y este es un código para lo mismo.

String jsonStr = "[{\r\n" + "\"name\":\"New York\",\r\n" + "\"number\": \"732921\",\r\n"+ "\"center\": {\r\n" + "\"latitude\": 38.895111,\r\n"  + " \"longitude\": -77.036667\r\n" + "}\r\n" + "},\r\n" + " {\r\n"+ "\"name\": \"San Francisco\",\r\n" +\"number\":\"298732\",\r\n"+ "\"center\": {\r\n" + "    \"latitude\": 37.783333,\r\n"+ "\"longitude\": -122.416667\r\n" + "}\r\n" + "}\r\n" + "]";

ObjectMapper mapper = new ObjectMapper();
MyPojo[] jsonObj = mapper.readValue(jsonStr, MyPojo[].class);

for (MyPojo itr : jsonObj) {
    System.out.println("Val of name is: " + itr.getName());
    System.out.println("Val of number is: " + itr.getNumber());
    System.out.println("Val of latitude is: " + 
        itr.getCenter().getLatitude());
    System.out.println("Val of longitude is: " + 
        itr.getCenter().getLongitude() + "\n");
}

Nota: MyPojo[].classes la clase que tiene getter y setter de propiedades json.

Resultado:

Val of name is: New York
Val of number is: 732921
Val of latitude is: 38.895111
Val of longitude is: -77.036667
Val of name is: San Francisco
Val of number is: 298732
Val of latitude is: 37.783333
Val of longitude is: -122.416667
Atul Sharma
fuente
1
Esto solucionó el problema que había tenido durante días, ninguna otra respuesta tenía sentido. Para cualquier otra persona que tenga el mismo error. Vale la pena señalar que si su JSON tiene varios objetos, debe devolver varios objetos. Había estado devolviendo MyObject, donde debería haber devuelto MyObject []
Aaria
8

Como se dijo, JsonMappingException: out of START_ARRAY tokenel mapeador de objetos de Jackson lanza una excepción , ya que espera un Object {}mientras que encontró una Array [{}]respuesta.

Una solución más simple podría reemplazar el método getLocationscon:

public static List<Location> getLocations(InputStream inputStream) {
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        TypeReference<List<Location>> typeReference = new TypeReference<>() {};
        return objectMapper.readValue(inputStream, typeReference);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Por otro lado, si no tienes un pojo como Location, podrías usar:

TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() {};
return objectMapper.readValue(inputStream, typeReference);
freedev
fuente
1
Gracias por compartir esta implementación alternativa. ¿Puede decir si existen ventajas o desventajas con el uso de CollectionTypevs. TypeReference?
JJD
1
TypeReferencela sintaxis es mucho más corta que la otra. No estoy seguro, si en algunos casos podría haber una contraindicación relacionada con el borrado de tipo ... pero en mi mundo TypeReferencees más fácil de usar y comprender.
freedev