Подтвердить что ты не робот

Не удалось прочитать JSON: нельзя десериализовать экземпляр hello.Country [] из токена START_OBJECT

У меня есть URL-адрес для отдыха, который дает мне все страны - http://api.geonames.org/countryInfoJSON?username=volodiaL.

Я использую RestTemplate из spring 3 для разбора возвращенного json в java-объекты:

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

Когда я запускаю этот код, я получаю исключение:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of hello.Country[] out of START_OBJECT token
 at [Source: [email protected]149; 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

Наконец, мой класс Country:

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

Проблема заключается в том, что возвращенный json содержит корневой элемент "geonames", который содержит массив элементов страны, например:

{
"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"
    }
]
}

Как сообщить RestTemplate преобразовать каждый элемент массива в объект Country?

4b9b3361

Ответ 1

Вам нужно сделать следующее:

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();

Было бы здорово, если бы вы могли использовать какую-то аннотацию, чтобы вы могли пропускать уровни, но это еще не возможно (см. this и это)

Ответ 2

Другое решение:

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

Использование универсального Object -List решило мою проблему, так как были и другие типы данных, такие как Boolean.

Ответ 3

В моем случае, я получал значение <input type="text"> с JQuery, и я сделал это следующим образом:

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

И я постоянно получал это исключение

com.fasterxml.jackson.databind.JsonMappingException: невозможно десериализовать экземпляр java.lang.String из токена START_OBJECT  в [Источник: [email protected]; строка: 1, столбец: 54] (через цепочку ссылок: com.springboot.domain.User [ "firstName" ]).

И я ударил головой, как час, пока не понял, что забыл написать .value после этого "firstName": inputFirstName[0].

Итак, правильным решением было:

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

Я пришел сюда, потому что у меня была эта проблема, и я надеюсь, что я спасу еще несколько часов страданий.

Приветствия:)

Ответ 4

Для Spring -boot 1.3.3 работает метод exchange() для List как в соответствующем ответе

Spring Data Rest - _links