Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB annotated POJO for JSON serialization in Jersey returns String for every field type

I am using Jersey to create a web service for a server component. Unfortunately I have a problem with the formatting of my JSON response, because the data is always formatted as string.

I have a simple JAXB annotated POJO with different field types:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class JaxbPojo {

    @XmlElement(name = "id_64")
    private Long id;

    @XmlElement(name = "desc")
    private String description;

    private Boolean active;

    // getters and setters
    ..
}

and a a simple resource, returning the incoming object:

@Path("/jaxb_pojo")
public class JaxbPojoResource {

    @POST
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces({ MediaType.APPLICATION_JSON })
    public JaxbPojo processBidRequest(JaxbPojo pojo) {
         return pojo;
    }

}

When sending a request to the resource with the following JSON data, the object is filled correctly inside the resource method. But the field types of the returned JSON data are always formatted as string:

me@host:/tmp $ cat simple_jaxb_pojo 
{"id_64":99,"desc":"simple JAXB POJO","active":true}

me@host:/tmp $ curl -X POST -H "Content-Type: application/json" --data-binary @simple_jaxb_pojo http://localhost/srvr/rest/jaxb_pojo
{"id_64":"99","desc":"simple JAXB POJO","active":"true"}

All used jar files (jsr311-api-1.1.1.jar, jersey-core-1.6.jar, jersey-json-1.6.jar, jersey-server-1.6.jar) are directly included in the tomcat/lib path. The JAX-RS library is used via Maven pom.xml with scope "provided":

<dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>jsr311-api</artifactId>
    <version>1.1.1</version>
    <scope>provided</scope>
</dependency>

My web.xml looks like this:

<servlet>
    <servlet-name>RestServlet</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.rest.RestResourcesApplication</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

..

<servlet-mapping>
    <servlet-name>RestServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

Am I missing something or do I maybe have to configure Jackson explicitly in a way that it is using the types of my POJO. I am fairly new to this subject, so I posted every information I have on this. I hope someone can help.

like image 611
henne83 Avatar asked Oct 18 '12 11:10

henne83


2 Answers

Interesting problem. I'm not sure exactly why this is happening but try adding:

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

to your Jersey servlet definition in web.xml. I thought Jersey required this to produce JSON but when I removed this init-param I saw the same issue that you're having.

like image 110
condit Avatar answered Nov 08 '22 01:11

condit


user463324 's solution is good. Normally, you can use this solution to convert your Java Objects to JSON and back. It is based on the Jackson library.

If you want to get JSON based on JAXB, There are some configuration options provided, so that you can control how things get serialized out and deserialized back. For the default configuration, you'll get string format, like your question pointed out.

To achieve more important JSON format changes, you will need to configure Jersey JSON procesor itself. Various configuration options could be set on an JSONConfiguration instance. The instance could be then further used to create a JSONConfigurated JSONJAXBContext, which serves as a main configuration point in this area. To pass your specialized JSONJAXBContext to Jersey, you will finally need to implement a JAXBContext ContextResolver:

    @Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {

    private final JAXBContext context;
    private final Set<Class> types;
    private Class[] ctypes = { JaxbPojo.class};
    public JAXBContextResolver() throws Exception {
        this.types = new HashSet(Arrays.asList(ctypes));
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(),
                ctypes);
    }

    @Override
    public JAXBContext getContext(Class<?> objectType) {
        return (types.contains(objectType)) ? context : null;
    }
}

You can refer to jersey' official document for detailed information.

like image 26
secondflying Avatar answered Nov 08 '22 02:11

secondflying