Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Jersey/Jackson to NOT use @XmlElement field annotation for JSON field naming

I am running a Jersey REST service. The POJO's which represent my resources are JAXB (XML) annotated simple Java classes (they are generated from a schema definition - so they have the annotations).

I want Jersey/Jackson to ignore the XML-Annotations. I did this configuration in my web.xml (as mentioned here):

  <init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
  </init-param>

I now expected that the @XMLElement annotation would not be used anymore for JSON field naming policy.

But looking at this java field (member)

@XmlElement(name = "person", required = true)
protected List<Person> persons;

I still get the following JSON representation:

....,"person":[{"name":"FooBar", ....... (person without the 's')

All other fields also still get their JSON names from the @XmlElement annotation instead from the Java field name.

I would like to achieve a JSON output as describe in the Jackson Full Data Binding (POJO) Example.

It works fine in simple tests like this (with my XML annotated classes):

  ObjectMapper mapper = new ObjectMapper(); 
  mapper.writeValue(System.out, myObject);

but embedded in Jersey I did not get the expected JSON output.

Are their other configuration options in Jersey to get the 'simple' POJO JSON representation (because this fits best to clients which have to deserialize the JSON result).

Thanks Klaus

Detailed solution

(1) Implement a ContextResolver for Jacksons ObjectMapper which creates an ObjectMapper that will not use annotations.

package foo.bar.jackson;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;

/**
 * Customized {@code ContextResolver} implementation that does not use any
 * annotations to produce/resolve JSON field names.
 */
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {

    private ObjectMapper objectMapper;

    /**
     * Creates a new instance.
     * 
     * @throws Exception
     */
    public JacksonContextResolver() throws Exception {
        this.objectMapper = new ObjectMapper().configure(
                DeserializationConfig.Feature.USE_ANNOTATIONS, false)
                .configure(SerializationConfig.Feature.USE_ANNOTATIONS, false);
        ;
    }

    /**
     * @see javax.ws.rs.ext.ContextResolver#getContext(java.lang.Class)
     */
    public ObjectMapper getContext(Class<?> objectType) {
        return objectMapper;
    }
}

(2) Register the ContextResolver Spring bean in your application.xml

<bean class="foo.bar.jackson.JacksonContextResolver"/>
like image 642
FrVaBe Avatar asked Feb 15 '11 15:02

FrVaBe


1 Answers

At low level, what is needed to make sure that ObjectMapper does NOT use JAXBAnnotationIntrospector, but only default JacksonAnnotationIntrospector. I think you should be able to just construct ObjectMapper (which does not add JAXB introspector by default), and register it via standard JAX-RS provider mechanism. This should override ObjectMapper that POJO mapper functionality would otherwise construct.

like image 135
StaxMan Avatar answered Sep 19 '22 15:09

StaxMan