JsonMappingException: z START_ARRAY tokenu

112

Biorąc pod uwagę następujący plik .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
            ]
    }
]

Przygotowałem dwie klasy reprezentujące zawarte dane:

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

...

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

Do parsowania treści z pliku .json używam Jacksona 2.2.x i przygotowałem następującą metodę:

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

Dopóki pominę tę centerwłaściwość, cała zawartość może zostać przeanalizowana. Jednak gdy próbuję przeanalizować współrzędne geograficzne, pojawia się następujący komunikat o błędzie:

com.fasterxml.jackson.databind.JsonMappingException: nie można deserializować instancji
com.example.GeoPoint z START_ARRAY tokenu pod adresem [Źródło: android.content.res.AssetManager$AssetInputStream@416a5850; wiersz: 5, kolumna: 25]
(przez łańcuch odwołań: com.example.Location ["centrum"])

JJD
źródło
dlaczego używasz jacksona, jeśli możesz po prostu przeanalizować go za pomocą parsera json
Shashank Agarwal
4
Twój ciąg JSON jest źle sformułowany, typ centerto tablica nieprawidłowych obiektów. Spróbuj zamienić [a ]z {a }w ciągu JSON wokół longitudei latitudetak będą obiekty.
Katona,
1
@Katona Dziękuję. Czy możesz zamienić swój komentarz na odpowiedź, abym mógł zamknąć pytanie ?!
JJD

Odpowiedzi:

75

Twój ciąg JSON jest źle sformułowany: typ centerto tablica nieprawidłowych obiektów. Wymień [i ]z {i }w ciągu około JSON longitudei latitudetak będą obiekty:

[
    {
        "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
źródło
1
Ten sam problem, który miałem, ale to szalone, ponieważ w jackson 2.6.3v był zupełnie inny szalony błąd, a przy 2.9.8v wszystko działało. Cholera, więc te błędy serializacji są tak irytujące.
brebDev
115

JsonMappingException: out of START_ARRAY tokenWyjątek jest generowany przez program mapowania obiektów Jacksona, ponieważ oczekuje an, Object {}podczas gdy znalazł Array [{}]w odpowiedzi.

Problem ten można rozwiązać poprzez wymianę Objectz Object[]w argumentu geForObject("url",Object[].class). Bibliografia:

  1. Ref.1
  2. Ref.2
  3. Pn.3
Abhijeet
źródło
9

Rozwiązałem ten problem jako weryfikację json z JSONLint.com, a następnie poprawienie go. A to jest kod na to samo.

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

Uwaga: MyPojo[].classjest to klasa mająca getter i setter właściwości json.

Wynik:

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
źródło
1
To rozwiązało problem, który miałem od wielu dni, żadne inne odpowiedzi nie miały sensu. Dla każdego, kto ma ten sam błąd. Warto zauważyć, że jeśli twój JSON ma wiele obiektów, musisz zwrócić wiele obiektów.
Zwracałem
8

Jak już powiedziano, program JsonMappingException: out of START_ARRAY tokenmapowania obiektów Jacksona zgłasza wyjątek , ponieważ oczekuje, Object {}że Array [{}]w odpowiedzi znalazł a .

Prostszym rozwiązaniem mogłoby być zastąpienie metody getLocations:

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

Z drugiej strony, jeśli nie masz typu pojo Location, możesz użyć:

TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() {};
return objectMapper.readValue(inputStream, typeReference);
freedev
źródło
1
Dziękujemy za udostępnienie tej alternatywnej implementacji. Czy możesz powiedzieć, czy są zalety lub wady korzystania z CollectionTypevs. TypeReference?
JJD,
1
TypeReferenceskładnia jest znacznie krótsza niż inne. Nie jestem pewien, czy w niektórych przypadkach może istnieć przeciwwskazanie związane z usunięciem typu ... ale w moim świecie TypeReferencejest po prostu łatwiejszy w użyciu i zrozumieniu.
freedev