Ne pouvait pas lire JSON: ne peut pas désérialiser l'instance de hello.Pays [] jeton d'objet "out of START"

j'ai l'url rest qui me donne tous les pays - http://api.geonames.org/countryInfoJSON?username=volodiaL .

j'utilise RestTemplate du printemps 3 pour analyser JSON retourné dans les objets java:

RestTemplate restTemplate = new RestTemplate();
Country[] countries = restTemplate.getForObject("http://api.geonames.org/countryInfoJSON?username=volodiaL",Country[].class);

quand j'exécute ce code j'obtiens une exception:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of hello.Country[] out of START_OBJECT token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@1846149; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:691)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:685)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.handleNonArray(ObjectArrayDeserializer.java:222)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:133)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:18)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2993)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2158)
    at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:225)
    ... 7 more

enfin ma classe de pays:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Country {
    private String countryName;
    private long geonameId;

    public String getCountryName() {
        return countryName;
    }

    public long getGeonameId() {
        return geonameId;
    }

    @Override
    public String toString() {
        return countryName;
    }
}

le problème est que le JSON retourné contient l'élément root "geonames" qui contient un tableau d'éléments de pays comme so:

{
"geonames": [
    {
        "continent": "EU",
        "capital": "Andorra la Vella",
        "languages": "ca",
        "geonameId": 3041565,
        "south": 42.42849259876837,
        "isoAlpha3": "AND",
        "north": 42.65604389629997,
        "fipsCode": "AN",
        "population": "84000",
        "east": 1.7865427778319827,
        "isoNumeric": "020",
        "areaInSqKm": "468.0",
        "countryCode": "AD",
        "west": 1.4071867141112762,
        "countryName": "Andorra",
        "continentName": "Europe",
        "currencyCode": "EUR"
    }
]
}

comment dire RestTemplate pour convertir chaque élément de tableau en objet Country ?

32
demandé sur Chepech 2014-07-21 15:54:51

5 réponses

Vous devez faire ce qui suit:

public class CountryInfoResponse {

   @JsonProperty("geonames")
   private List<Country> countries; 

   //getter - setter
}

RestTemplate restTemplate = new RestTemplate();
List<Country> countries = restTemplate.getForObject("http://api.geonames.org/countryInfoJSON?username=volodiaL",CountryInfoResponse.class).getCountries();

Ce serait génial si vous pouviez utiliser un certain type de l'annotation pour vous permettre de sauter des niveaux, mais il n'est pas encore possible (voir ce et ce )

36
répondu geoand 2014-07-21 12:07:27

une autre solution:

public class CountryInfoResponse {
  private List<Object> geonames;
}

Usage d'un générique objet -List a résolu mon problème, car il y avait d'autres types de données comme booléen aussi.

9
répondu vonox7 2015-02-05 16:59:08

dans mon cas, j'obtenais la valeur de <input type="text"> avec JQuery et je l'ai fait comme ceci:

var newUserInfo = { "lastName": inputLastName[0].value, "userName": inputUsername[0].value,
 "firstName": inputFirstName[0] , "email": inputEmail[0].value}

Et j'ai été constamment cette exception

com.fasterxml.Jackson.databind.JsonMappingException: ne peut pas désérialiser l'instance de java.lang.String out of START_OBJECT token à [Source: java.io.PushbackInputStream@39cb6c98; ligne: 1, colonne: 54] (par chaîne de référence: com.springboot.domaine.Utilisateur["prenom"]).

et je me suis cogné la tête pendant une heure jusqu'à ce que je réalise que j'avais oublié d'écrire .value après ce "firstName": inputFirstName[0] .

ainsi, la solution correcte était:

var newUserInfo = { "lastName": inputLastName[0].value, "userName": inputUsername[0].value,
 "firstName": inputFirstName[0].value , "email": inputEmail[0].value}

je suis venu ici parce que j'avais ce problème et j'espère sauver quelqu'un d'autre des heures de misère.

Cheers:)

3
répondu Filip Savic 2017-05-31 17:31:42

si vous voulez éviter d'utiliser un Class et List<Object> genomes supplémentaires, vous pouvez simplement utiliser un Map .

la structure de données se traduit par Map<String, List<Country>>

String resourceEndpoint = "http://api.geonames.org/countryInfoJSON?username=volodiaL";

Map<String, List<Country>> geonames = restTemplate.getForObject(resourceEndpoint, Map.class);

List<Country> countries = geonames.get("geonames");
0
répondu clD 2018-09-04 17:03:04

pour amortisseur à ressort 1.3.3 la méthode exchange () pour List fonctionne comme dans la réponse

Printemps des Données Reste - _links

-1
répondu tyler 2017-05-23 11:54:10