JsonMappingException: dal token START_ARRAY


112

Dato il seguente file .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
            ]
    }
]

Ho preparato due classi per rappresentare i dati contenuti:

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

...

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

Per analizzare il contenuto dal file .json utilizzo Jackson 2.2.xe ho preparato il seguente metodo:

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;
}

Finché tralascio la centerproprietà, tutto il contenuto può essere analizzato. Tuttavia, quando provo ad analizzare le coordinate geografiche, ricevo il seguente messaggio di errore:

com.fasterxml.jackson.databind.JsonMappingException: impossibile deserializzare l'istanza di
com.example.GeoPoint dal token START_ARRAY in [Fonte: android.content.res.AssetManager$AssetInputStream@416a5850; riga: 5, colonna: 25]
(tramite la catena di riferimento: com.example.Location ["center"])


perché stai usando jackson se puoi semplicemente analizzarlo con json parser
Shashank Agarwal

4
La tua stringa JSON non è valida, il tipo di centerè un array di oggetti non validi. Prova a sostituire [e ]con {e }nella stringa JSON intorno longitudee latitudequindi saranno oggetti.
Katona

1
@Katona Grazie. Puoi convertire il tuo commento in una risposta in modo che io possa chiudere la domanda ?!
JJD

Risposte:


75

La tua stringa JSON non è valida: il tipo di centerè un array di oggetti non validi. Sostituisci [e ]con {e }nella stringa JSON intorno longitudee latitudequindi saranno oggetti:

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

1
Lo stesso problema ho avuto, ma è pazzesco poiché in jackson 2.6.3v c'era un errore pazzo completamente diverso, e con 2.9.8v tutto ha funzionato. Dannazione, quindi questi errori di serializzazione sono così fastidiosi.
brebDev

114

JsonMappingException: out of START_ARRAY tokenL'eccezione viene lanciata dal mappatore oggetti Jackson in quanto si aspetta un Object {}mentre ha trovato un Array [{}]in risposta.

Questo può essere risolto sostituendo Objectcon Object[]nell'argomento per geForObject("url",Object[].class). Riferimenti:

  1. rif.1
  2. rif.2
  3. rif.3

9

Ho risolto questo problema verificando il json da JSONLint.com e quindi correggendolo. E questo è il codice per lo stesso.

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[].classè la classe che ha getter e setter delle proprietà json.

Risultato:

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

1
Questo ha risolto il problema che ho avuto per giorni, nessun'altra risposta aveva senso. Per chiunque altro abbia lo stesso errore. Vale la pena notare che se il tuo JSON ha più oggetti, devi restituire più oggetti. Stavo restituendo MyObject, dove avrei dovuto restituire MyObject []
Aaria

8

Come detto, l' JsonMappingException: out of START_ARRAY tokeneccezione viene lanciata dal mappatore di oggetti Jackson poiché si aspetta un Object {}mentre ha trovato un Array [{}]in risposta.

Una soluzione più semplice potrebbe essere sostituire il metodo 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;
}

D'altra parte, se non hai un pojo come Location, potresti usare:

TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() {};
return objectMapper.readValue(inputStream, typeReference);

1
Grazie per aver condiviso questa implementazione alternativa. Puoi dire se ci sono vantaggi o svantaggi nell'utilizzo di CollectionTypevs. TypeReference?
JJD

1
TypeReferencela sintassi è molto più breve dell'altra. Non sono sicuro, se in alcuni casi potrebbe esserci una controindicazione relativa al tipo di cancellazione ... ma nel mio mondo TypeReferenceè solo più facile da usare e da capire.
freedev
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.