1

I want response by using single function like:

@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getVolume(){
    ...enter code here
    return Response.ok().entity(VolDetail).build();
}

Output shoulb be like:

xml:
<volume>
   <status>available</status>
</volume>

JSON:
{"volume":{"status":"available"}}

where volume is a POJO class.

The problem is that I am not getting root element in JSON. I tried JSON object binding but its not working properly.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
chandan singh
  • 271
  • 2
  • 9
  • What JSON provider are you using. Can you show your dependencies – Paul Samsotha Apr 06 '15 at 15:06
  • My pojo class: @XmlRootElement(name="volume") @JsonRootName(value="volume") public class VolumeDetail { public String status; – chandan singh Apr 07 '15 at 07:05
  • Thanks for replying..!! My pojo class: @XmlRootElement(name="volume") @JsonRootName(value="volume") public class VolumeDetail { public String status; } I tried this in my getVolume() function mentioned above to print in log : ObjectMapper om = new ObjectMapper().enable(SerializationConfig.Feature.WRAP_ROOT_VALUE); String jsonResponse = om.writeValueAsString(response); _log.info(jsonResponse); – chandan singh Apr 07 '15 at 08:57
  • See answer below. I have tested it, and it works fine – Paul Samsotha Apr 07 '15 at 08:59

1 Answers1

2

Assuming you're using Jackson. You can configure the ObjectMapper to WRAP_ROOT_VALUE. You would do that in the ContextResolver. With Jackson 1.x, it would look like

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper>  {
    
    final ObjectMapper mapper = new ObjectMapper();
    
    public ObjectMapperContextResolver() {
        mapper.configure(Feature.WRAP_ROOT_VALUE, true);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }  
}

With Jackson 2.x, it would look like

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper>  {
    
    final ObjectMapper mapper = new ObjectMapper();
    
    public ObjectMapperContextResolver() {
        mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }  
}

Your POJO should be annotated with @XmlRootElement(name = "volume") or @JsonRootName("volume")

If you don't want all your objects wrapped, you can configure different mappers for different classes, as seen here

Edit

With the above solution, only @JsonRootName will work. The reason is that by using our own ObjectMapper, we override the behavior of a JAXB annotation support configuration. We could explicitly add the support back by mapper.registerModule(new JaxbAnnotationModule());

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • I implemented this ObjectMapperContextResolver. But neither its invoking getContext() nor constructor. I am not getting any relationship that how it will attach to my pojo or resource class. – chandan singh Apr 07 '15 at 09:00
  • How do you do your configuration? How are your `@Path` classes discovered? You can register this class the same way. Either with package scanning, or explicitly registering it. Also make sure you are using the correct Jackson version. If you still need help, update your original post with your configuration (either web.xml, or ResourceConfig)` and show all your dependencies. Don't put any updates in comments. There's an "edit" link under your post, to add updates – Paul Samsotha Apr 07 '15 at 09:03
  • As far as the relationship, JAX-RS uses `MessageBodyWriter`s and `MessageBodyReader`s to marshal and unmarshal. In the case of a request for a resource, The `MessageBodyWriter` used (provided by Jackson), will see the response is a `Volume` type, and call `getContext` on the `ContextResolver`, passing in the class. You can use that class to check with mapper to use. In the case above, it doesn't matter what class, the same mapper will be used – Paul Samsotha Apr 07 '15 at 09:07
  • Actually we are using spring framework for initialization. I think we are just giving path @Path and it automatically comes to the respective get or post method. Actually i am getting response in both the format but the only problem is that i want root element in JSON format. Can you suggest me that how i instantiate ObjectMapperContextResolver class and register my POJO class to it. I found this post, but here also they are instantiating in main method : http://stackoverflow.com/questions/18872931/custom-objectmapper-with-jersey-2-2-and-jackson-2-1 – chandan singh Apr 07 '15 at 13:43
  • Again, if you want help, show your configuration. I can show you four different ways to configure it, but it may not fit your current configuration. There needs to be some Jersey configuration for Jersey to work. If you have absolutely no idea, start with you web.xml. If you don't have one, then you must have a ResourceConfig/Application subclass. And show all your dependencies. Without that, I cannot help you. I do not want to post four different possible configurations, that may or may not work. – Paul Samsotha Apr 07 '15 at 13:49