Dec Clarke
Dec Clarke

Reputation: 53

RestTemplate: Can not deserialize instance of OBJECT out of START_OBJECT token

I'm trying out the RestTemplate stuff from spring. I'm trying to read in this JSON data: JSON Data. The data is a a key value pair in which the key is "geonames" and the value is an array of "geoname" objects.

I have a Geoname class to handle the input. This class also has getters and setters in it. I then have an app class that just runs a main method to invoke a RestTemplate object:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Geoname {
    private String name;
    private long lat;
    private long lng;
    private String countrycode;
}

App.java

public class App 
{
    public static void main( String[] args )
    {
        String jsonUrl = "http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo";

        RestTemplate template = new RestTemplate();
        ResponseEntity<Geoname[]> entity = template.getForEntity(jsonUrl, Geoname[].class);
        List<Geoname> data = Arrays.asList(entity.getBody());

        System.out.print("Success!");
    }
}

This is my error output:

Exception in thread "main" org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of com.declan.Geoname[] out of START_OBJECT token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@54fc3ac5; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.declan.Geoname[] out of START_OBJECT token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@54fc3ac5; line: 1, column: 1]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:208)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:200)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:96)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:812)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:796)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:576)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:529)
    at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:261)
    at com.declan.App.main(App.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.declan.Geoname[] out of START_OBJECT token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@54fc3ac5; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:835)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:831)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.handleNonArray(ObjectArrayDeserializer.java:232)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:139)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:17)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3560)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2660)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:205)
    ... 13 more

I've tried this setup, i've tried using getForObject like on the spring documentation, I've tried searching here on stackoverflow and using the common answer of mapping to a list. I've even tried creating a Geonames class that contained just an array or Geoname objects but that didn't work either...Same error all the time. Perhaps, I'm not reading the Json correctly but if someone could lend me a pair of eyes I'd be grateful. :D

Cheers!

EDIT

Okay, I now have this new class and it now makes the GET request for the JSON data. However, after a debug, the ResponseEntity body has the array set to null. Do I need to instantiate the array in Geonames manually?

@JsonIgnoreProperties(ignoreUnknown = true)
public class Geonames {
    @JsonProperty("geonames")
    Geoname[] geonames;

    public void setGeonames(Geonames[] geonames) {
        this.geonames = geonames;
    }

    public void getGeonames() {
        return geonames;
    }
}

Upvotes: 2

Views: 8144

Answers (1)

Dec Clarke
Dec Clarke

Reputation: 53

Resolved. Turns out that the null was because the JSON link had a max hits per hour limit. By creating my own account on the site, the api gave me my own limits. So the response body then populated with data.

Upvotes: 1

Related Questions