views:

756

answers:

1

I'm having trouble getting Jackson to correctly deserialize json into an object when calling a service (specifically we're using Jackson's ability to use JAXB annotations since we also want the service to use XML). I'm using Spring MVC and I'm using the RestTemplate class to make calls to the service.

Here is where I setup the MappingJacksonHttpMessageConverter for my junit:

ObjectMapper jsonMapper = new ObjectMapper();
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
jsonMapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
jsonMapper.getSerializationConfig().setAnnotationIntrospector(introspector);
jsonMapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);
MappingJacksonHttpMessageConverter jacksonConverter = new MappingJacksonHttpMessageConverter();
jacksonConverter.setObjectMapper(jsonMapper);
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(jacksonConverter);
template.setMessageConverters(converters);

And I call the service like so:

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/json");
HttpEntity<String> requestEntity = new HttpEntity<String>(requestHeaders);
ResponseEntity<NamedSystem> responseEntity = template.exchange(baseURL + "/{NamedSystemId}", 
        HttpMethod.GET, requestEntity, NamedSystem.class, orgId1);

My NamedSystem class is set up like so:

@XmlRootElement(name = "NamedSystem", namespace = "http://schemas.abc.workplace.com/NamedSystem")
public class NamedSystem {
    private String id;
    private String name;
    private String description;
    private Set<NamedSystemAlias> aliases;
    private String href;

    @XmlAttribute(required = false, name = "id")
    public String getId() {
        return id;
    }


    public void setId(String id) {
        this.id = id;
    }


    @XmlAttribute(required = false, name = "name")
    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    @XmlAttribute(required = false, name = "description")
    public String getDescription() {
        return description;
    }


    public void setDescription(String description) {
        this.description = description;
    }


    @XmlElementWrapper(required = false, name = "aliases", namespace = "http://schemas.abc.workplace.com/NamedSystem")
    @XmlElement(required = false, name = "alias", namespace = "http://schemas.abc.workplace.com/NamedSystem")
    public Set<NamedSystemAlias> getAliases() {
        return aliases;
    }


    public void setAliases(Set<NamedSystemAlias> aliases) {
        this.aliases = aliases;
    }

    @XmlAttribute(required = true, name = "href")
    public String getHref() {
        return href;
    }


    public void setHref(String href) {
        this.href = href;
    }
}

This is the error that results:

org.springframework.web.client.ResourceAccessException: I/O error: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]; nested exception is org.codehaus.jackson.map.JsonMappingException: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]
 at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
....
Caused by: org.codehaus.jackson.map.JsonMappingException: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]
 at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:159)
 at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:247)
 at org.codehaus.jackson.map.deser.StdDeserializer.reportUnknownProperty(StdDeserializer.java:366)
 at org.codehaus.jackson.map.deser.StdDeserializer.handleUnknownProperty(StdDeserializer.java:352)
 at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:543)
 at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:402)
 at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:287)
 at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:1588)
 at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1172)
 at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:132)
 at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:154)
 at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:74)
 at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:619)
 at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1)
 at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:446)
 ... 32 more

It seems it doesn't recognize the rootElement 'NamedSystem' to be able to deserialize. How would I get it to do that? I've seen examples that use the same JAXB annotations and they work fine so I'm not sure what's different about my case or how I might force it to correctly deserialize it. If anyone can offer any help, I'd appreciate it.

A: 

If anyone comes along this kind of problem, this might fix it for you: http://stackoverflow.com/questions/3303287/enable-jackson-to-not-output-the-class-name-when-serializing-using-spring-mvc

See my answer and follow the link for an example.

AHungerArtist