Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Jackson Object Mapper in RestEasy

I've been asked to beautify default Jackson JSON coming out of a RestEasy endpoint. I did some research on Jackson and wrote some standalone code to be able to suppress nulls, customize data formats etc. Now the challenge is injecting this code in RestEasy's JSON serialization.

Judging from the forum posts this is trivial in Spring, however doesn't seem to be the case in RestEasy. I wrote a ContextResolver and configured as resteasy.provider in context params in web.xml (on Tomcat) but that prevents the webapp from loading on Tomcat.

Now I'm trying to extend javax.ws.rs.core.Application and provide a ContextResolver but making no progress. Is this straight forward, has anyone done this? Any help is greatly appreciated.

like image 783
codegeek Avatar asked Dec 14 '11 01:12

codegeek


People also ask

Does RESTEasy use Jackson?

Resteasy supports both Jackson 1.9. x and Jackson 2.2.

How does Jackson ObjectMapper work?

The Jackson ObjectMapper can parse JSON from a string, stream or file, and create a Java object or object graph representing the parsed JSON. Parsing JSON into Java objects is also referred to as to deserialize Java objects from JSON. The Jackson ObjectMapper can also create JSON from Java objects.

What is RESTEasy Jackson?

Jackson, RESTEasy. RESTEasy is JBOSS provided implementation of JAX-RS specification for building RESTful Web Services and RESTful Java applications. Though this is not limited to be used in JBOSS only, and you can use with other servers also. Jackson is is a multi-purpose Java library for processing JSON data format.

What is ObjectMapper readValue in Java?

The simple readValue API of the ObjectMapper is a good entry point. We can use it to parse or deserialize JSON content into a Java object. Also, on the writing side, we can use the writeValue API to serialize any Java object as JSON output.


2 Answers

I found a nicer way of modifying the Jackson SerializationConfig - you can intercept the ObjectMapper creation by using a JAX-RS ContextResolver.

@Provider @Produces(Array(MediaType.APPLICATION_JSON)) class JacksonConfig extends ContextResolver[ObjectMapper] {    val mapper = new ObjectMapper()   mapper.getSerializationConfig.setSerializationInclusion(Inclusion.NON_NULL)    def getContext(objectType: Class[_]) = mapper } 

You will need to register with RESTEasy in one of the following ways:

  • Return it as a class or instance from a javax.ws.rs.core.Application implementation
  • List it as a provider with resteasy.providers
  • Let RESTEasy automatically scan for it within your WAR file. See Configuration Guide
  • Manually add it via ResteasyProviderFactory.getInstance().registerProvider(Class) or registerProviderInstance(Object)

Reference: RESTEasy docs

Reference: Nicklas Karlsson on the JBoss forums

Please note that this works with RESTEasy 2.3.2 which ships as a module in JBoss 7.1.1.Final, but does not appear to work with RESTEasy 3.0-beta5.

like image 183
James Baxter Avatar answered Oct 06 '22 14:10

James Baxter


Ok,I figured it out, I was able to do this by writing a custom JacksonJsonProvider based on the Jackson FAQ: JAX-RS.The code is as follows:

@Provider public class QBOJacksonJsonProvider extends JacksonJsonProvider {     public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";      @Override     public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {         Log.info(getClass(), "In custom JSON provider");         //get the Object Mapper         ObjectMapper mapper = locateMapper(type, mediaType);         // Suppress null properties in JSON output         mapper.getSerializationConfig().setSerializationInclusion(org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_NULL);         // Set human readable date format         SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);         mapper.getSerializationConfig().setDateFormat(sdf);          super.writeTo(value, type, genericType, annotations, mediaType, httpHeaders, entityStream);     } } 
like image 20
codegeek Avatar answered Oct 06 '22 15:10

codegeek