无法读取JSON:无法反序列化START_OBJECT令牌中的hello.Country []实例

时间:2014-07-21 11:54:51

标签: java spring resttemplate fasterxml

我有所有国家/地区的休息网址 - http://api.geonames.org/countryInfoJSON?username=volodiaL

我使用Spring 3中的RestTemplate将返回的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: 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

最后我的国家班:

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对象?

5 个答案:

答案 0 :(得分:41)

您需要执行以下操作:

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

如果您可以使用某种注释来跳过级别,那就太棒了,但它还不可能(请参阅thisthis

答案 1 :(得分:9)

另一种解决方案:

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

使用泛型 Object -List解决了我的问题,因为还有其他数据类型,如Boolean。

答案 2 :(得分:3)

在我的情况下,我使用JQuery获得了<input type="text">的价值,我这样做了:

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

我不断得到这个例外

  

com.fasterxml.jackson.databind.JsonMappingException:无法从START_OBJECT令牌中反序列化java.lang.String的实例    在[来源:java.io.PushbackInputStream@39cb6c98; line:1,column:54](通过引用链:com.springboot.domain.User [&#34; firstName&#34;])。

我把头撞了一个小时,直到我意识到在.value之后忘记写"firstName": inputFirstName[0]

所以,正确的解决方案是:

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

我来到这里是因为我遇到了这个问题,我希望能帮助别人节省数小时的痛苦。

干杯:)

答案 3 :(得分:0)

如果您想避免使用额外的ClassList<Object> genomes,则只需使用Map

数据结构转换为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");

答案 4 :(得分:-1)

对于Spring-boot 1.3.3,List的方法exchange()正在工作 如相关答案

Spring Data Rest - _links