JsonMappingException: sur le jeton START_ARRAY

112

Compte tenu du fichier .json suivant:

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

J'ai préparé deux classes pour représenter les données contenues:

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

...

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

Afin d'analyser le contenu du fichier .json, j'utilise Jackson 2.2.x et j'ai préparé la méthode suivante:

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

Tant que je laisse de côté la centerpropriété, tout le contenu peut être analysé. Cependant, lorsque j'essaie d'analyser les coordonnées géographiques, je me retrouve avec le message d'erreur suivant:

com.fasterxml.jackson.databind.JsonMappingException: impossible de désérialiser l'instance de
com.example.GeoPoint hors du jeton START_ARRAY à [Source: android.content.res.AssetManager$AssetInputStream@416a5850; ligne: 5, colonne: 25]
(via la chaîne de référence: com.example.Location ["center"])

JJD
la source
pourquoi utilisez-vous jackson si vous pouvez simplement l'analyser avec json parser
Shashank Agarwal
4
Votre chaîne JSON est mal formée, le type de centerest un tableau d'objets non valides. Essayez de remplacer [et ]avec {et }dans la chaîne JSON autour longitudeet latitudeils seront donc des objets.
Katona
1
@Katona Merci. Pouvez-vous s'il vous plaît convertir votre commentaire en réponse afin que je puisse fermer la question?!
JJD

Réponses:

75

Votre chaîne JSON est malformée: le type de centerest un tableau d'objets invalides. Remplacez [et ]par {et }dans la chaîne JSON autour longitudeet latitudeils seront donc des objets:

[
    {
        "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
la source
1
Le même problème que j'ai eu, mais c'est fou car dans jackson 2.6.3v il y avait une erreur folle totalement différente, et avec 2.9.8v tout fonctionnait. Bon sang, donc ces erreurs de sérialisation sont si ennuyeuses.
brebDev
114

JsonMappingException: out of START_ARRAY tokenexception est levée par le mappeur d'objets Jackson car il attend un Object {}alors qu'il a trouvé une Array [{}]réponse in.

Cela peut être résolu en remplaçant Objectpar Object[]dans l'argument pour geForObject("url",Object[].class). Références:

  1. Réf.1
  2. Réf.2
  3. Réf.3
Abhijeet
la source
9

J'ai trié ce problème en vérifiant le json de JSONLint.com, puis en le corrigeant. Et c'est le code pour le même.

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

Remarque: MyPojo[].classla classe a-t-elle un getter et un setter de propriétés json.

Résultat:

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
la source
1
Cela a résolu le problème que j'avais depuis des jours, aucune autre réponse n'avait de sens. Pour toute autre personne ayant la même erreur. Il convient de noter que si votre JSON contient plusieurs objets, vous devez renvoyer plusieurs objets. J'avais renvoyé MyObject, où j'aurais dû renvoyer MyObject []
Aaria
8

Comme dit, l' JsonMappingException: out of START_ARRAY tokenexception est levée par le mappeur d'objets Jackson car il attend un Object {}alors qu'il a trouvé une Array [{}]réponse in.

Une solution plus simple pourrait être de remplacer la méthode getLocationspar:

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'un autre côté, si vous n'avez pas de pojo comme Location, vous pouvez utiliser:

TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() {};
return objectMapper.readValue(inputStream, typeReference);
Freedev
la source
1
Merci de partager cette implémentation alternative. Pouvez-vous dire s'il y a des avantages ou des inconvénients à utiliser CollectionTypevs. TypeReference?
JJD
1
TypeReferencela syntaxe est beaucoup plus courte que l'autre. Pas sûr, si dans certains cas il pourrait y avoir une contre-indication liée à l'effacement de type ... mais dans mon monde, TypeReferencec'est juste plus facile à utiliser et à comprendre.
Freedev