users@jersey.java.net

Re: [Jersey] customizing JSON rendering in Jersey

From: Jakub Podlesak <Jakub.Podlesak_at_Sun.COM>
Date: Tue, 29 Apr 2008 09:17:38 +0200

Hi Arul,

please look for a solution in line...

On Mon, Apr 28, 2008 at 06:46:23PM -0600, Arul Dhesiaseelan wrote:
> Hi,
>
> I would like to customize JSON rendering in Jersey. Here is my resource
> class and associated JAXB classes.
>
> CustomerResource.java
>
> @Singleton
> @Path("/customers")
> public class CustomerResource {
>
> private static Map<Long, Customer> customers = new
> ConcurrentHashMap<Long, Customer>();
>
> @GET @Path("/list")
> @ProduceMime({"application/json"})
> public Customers getCustomers() throws IOException {
> Customers c = new Customers();
> c.setCustomers(customers.values());
> return c;
> }
>
> }
> Customers.java
>
> @XmlRootElement
> public class Customers {
> private Collection<Customer> customers;
>
> public Collection<Customer> getCustomers() {
> return customers;
> }
>
> public void setCustomers(Collection<Customer> c) {
> this.customers = c;
> }
> }
>
> Customer.java
> @XmlRootElement(name = "customer")
> public class Customer {
> private Long id;
> private String name;
> //getters and setters
> }
>
> When I access the "/customers/list" URL, I get the following JSON response.
>
> {"customers":{"customers":[{"id":"2","name":"Test2"},{"id":"1","name":"Test1"}]}}
>
> I am not sure why the customers tag is listed twice. I would like to
> generate something like

that is because the original xml (JAXB generated) looks like:

<customers><customers><id>2</id2><name>Test2</name></customers>...
^^^
the first <customers/> element corresponds to Customers.class
while the second one corresponds to Customers#customers collection

It is probably a regression, because the very first (wrapping) element should
be stripped off by default. Which Jersey build do you use?

>
> {"customers":[{"id":"2","name":"Test2"},{"id":"1","name":"Test1"}]}
>
> How do I customize JSON rendering in Jersey?

You will need to implement your custom JAXB context resolver. In your case
not only due to the above mentioned regression, but also to deal with
one-element customer collections (see [1] for details).

Your resolver could look like (did not test it):

    @Provider
    public class JAXBContextResolver implements ContextResolver<JAXBContext> {

        private JAXBContext context;
        private Class[] types = {Customers.class, Customer.class};

        public JAXBContextResolver() throws Exception {
            Map props = new HashMap<String, Object>();
            props.put(JSONJAXBContext.JSON_NOTATION, "MAPPED");
            props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE);
            props.put(JSONJAXBContext.JSON_ARRAYS, "[\"customers\"]");
            this.context = new JSONJAXBContext(types, props);
        }

        public JAXBContext getContext(Class<?> objectType) {
            return (types[0].equals(objectType) || types[1].equals(objectType)) ? context : null;
        }
    }

HTH,

~Jakub

[1]http://blogs.sun.com/japod/entry/missing_brackets_at_json_one

>
> Please clarify.
>
> Thank you,
> Arul
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>