Better JSON Available In Jersey

Since today a better support for JSON data generated out of JAXB beans is available in Jersey.

The main improvement is a simpler default JSON data format.
Badgerfish convention was replaced by a new one, a slightly simplified so called mapped convention from Jettison. JSON convention used for particular beans is now also fully configurable by the end user.
I will show how the configuration could be done below.

The main differences between available formats could be described using the following example.
Lets start with a very simple JAXB bean. You can see the source code, XML output and then
all formats you can get from Jersey resource:


@XmlRootElement
public static class SimpleJaxbBean {
public String name = "Franz";
public String surname = "Kafka";
}

XML output:


<simpleJaxbBean>
<name>Franz</name>
<surname>Kafka</surname>
</simpleJaxbBean>

Badgerfish format:


{"simpleJaxbBean":{"name":{"$":"Franz"},"surname":{"$":"Kafka"}}}

Mapped format (Jettison):


{"simpleJaxbBean":{"name":"Franz","surname":"Kafka"}}

and finally Jersey default format:


{"name":"Franz","surname":"Kafka"}

If you want to control, which format is actually used for which JAXB bean,
you can do it by providing Jersey runtime with your own custom JAXBContext classes
via implementing custom ContextResolver.

You can get inspired by following example:


@Path("/jsonFormats")
public class SimpleJsonResource {
@Provider
public static class JAXBContextResolver implements ContextResolver<JAXBContext> {

private JAXBContext context;
private Class[] types = {SimpleJaxbBean.class};

public JAXBContextResolver() throws Exception {
Map<String, Object> props = new HashMap<String, Object>();
props.put(JSONJAXBContext.JSON_NOTATION, "MAPPED_JETTISON");
props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.FALSE);
this.context = new JSONJAXBContext(types, props);
}

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

@XmlRootElement
public static class SimpleJaxbBean {
public String name = "Franz";
public String surname = "Kafka";
}

@GET
@ProduceMime({"application/json", "application/xml"})
public SimpleJaxbBean getJson() {
return new SimpleJaxbBean();
}
}

The following options are available for the JSONJAXBContext.JSON_NOTATION
property, where the first one is the default value:


  • MAPPED
  • MAPPED_JETTISON
  • BADGERFISH

In the future i plan to add more properties so that the JSON serialization and deserialization
is highly configurable.

Comments:

Congrats!

What about showing how to install this on top of the GFv3 M2 that was announced today?

- eduard/o

Posted by Eduardo Pelegri-Llopart on February 22, 2008 at 04:53 PM CET #

This is definitely a welcome change over badgerfish, but it's proving confusing to me for things that return lists. The default behavior is to take a JAXB bean that would be serialized as:

<list>
<item>
<k>1</k>
<v>A</v>
</item>
<item>
<k>2</k>
<v>B</v>
</item>
</list>

and turn it into

{"item":["k":"1","v":"A","k":"2","v":"B"]}

which is clearly not what i want...help?

Posted by Eric Jensen on February 29, 2008 at 12:17 PM CET #

Hi Eric. Thanks for pointing that out. It should be something like: {"item":[{"k":"1", "v":"A"},{"k":"2","v":"B"}]}, right? I am going to create a test case for this and fix it.

Posted by Jakub on March 03, 2008 at 03:22 AM CET #

Eric, i responded too fast. The above mentioned JSON gets produced just fine.
Please see the unit test at https://jersey.dev.java.net/source/browse/jersey/trunk/jersey/test/com/sun/ws/rest/impl/json/ for a similar case.
Could you please give an example of desired JSON expression you want to get produced?
Thanks,
~Jakub

Posted by Jakub on March 03, 2008 at 08:18 AM CET #

How to control the marshalling process when i create a web method which produces XML and json ouputs from an object serialization ? In my case the object is annoted with Jaxb annotations like (@XmlAttribute or @XmlList) and i want to export this object to a custom XML and a simply json ({ id:1, name:"name", categories:[{id:1, name:"name"}]} and not ({@id:1 $:"name"}). In fact i want to bypass the jaxb customization in some cases :-)

Posted by Julien on July 05, 2008 at 07:06 AM CEST #

Julien, it seems you are giving me another reason to make internal JAXB model information accessible to outside. Please stay tuned. I will talk to Martin Grebac, who actually owns JAXB and let you know (he is off on vacation this week).

Posted by Jakub on July 07, 2008 at 11:05 AM CEST #

I just ran into the same problem as Julien, so I thought I'd ping here to see if there was any update on this yet. I just need to get rid of the "@" prefix on attribute names. Even if there's not an elegant way to do this yet, I'd settle for a hacky way for now. :)

Posted by Tim on July 23, 2008 at 07:19 PM CEST #

I am sorry, but the only thing i can promise at the moment is that i will hopefully have time for it after 0.9 release in August. I would indeed love if i could write some better answer.

Posted by Jakub on July 25, 2008 at 01:24 PM CEST #

Tim: the initial support for serialization of attributes without the initial '@' in the name has been just commited to the main trunk. It should soon become available at
http://download.java.net/maven/2/com/sun/jersey/jersey-json/0.11-ea-SNAPSHOT/

The way to make it work for you is to provide an additional property to your custom JAXBContext resolver with a list of affected attribute names. E.g. for attributes i, j you would add:

props.put(JSONJAXBContext.JSON_ATTRS_AS_ELEMS, "[\\"i\\",\\"j\\"]");

so that it gets serialized out as

{"i":"one","j":"two"}

instead of

{"@i":one","@j":"two"}

Posted by Jakub on September 12, 2008 at 04:54 AM CEST #

Awesome, thanks Jakub! Is there any way to enable this for all elements (like "\*")?

Posted by Tim on September 12, 2008 at 11:25 AM CEST #

Not yet. The thing is that i need to better integrate with JAXB. And it might require certain changes on JAXB side. The plan is to look at that after Jersey 1.0 is released.

Posted by Jakub on September 15, 2008 at 03:28 AM CEST #

Just wondering about how to specify a ContextResolver based on MimeType. I'm returning both XML and JSON using JAXB and I need to customize them both (arrays, as above for JSON and some namespace issues for XML). How can I specify a resolver for JSON vs XML, since they both would be JAXBContext Providers? Thanks.

Posted by Clark on November 18, 2008 at 05:07 PM CET #

Clark: JSONJAXBContext is just a wrapper. Besides JSON specific properties, you can pass it also properties for the underlying JAXBContext, and it should work all right. If you need a very special JAXBContext implementation, just override the standard one, and it should work as well (wrapped instance is instantiated via standard JAXB API JAXBContext.newInstance factory method, so your implementation should be picked up automatically).

Posted by Jakub on November 19, 2008 at 01:15 AM CET #

Hi,
something I'd like to do, which I cannot find, is how to set a default notation (natural in my case) throughout the whole application.

Is there a way to set a notation configuration for either whole application or all classes?

I've seen many examples where this is linked to the class - but that forces you to specify the class on the code. Every time you have a new class you want to notate, then you have to specify it on the Class[] types.

Thanks a lot

Posted by xmariachi on June 11, 2009 at 02:58 AM CEST #

I was looking for unwrapped json and found it at last. By-by DWR! I'm happy :)

Posted by Ashitkin Alexander on October 19, 2009 at 02:28 AM CEST #

Great post and draw. Thank you for sharing.!!@!

Posted by links of london on November 25, 2009 at 07:38 PM CET #

That’s something,That's what I was thinking.Brilliant idea.

Posted by uvip on December 18, 2009 at 12:01 AM CET #

I have sub-classed the ContextResolver<JAXBContext> so that JSON NATURAL format is used with the classes I need to bind. However, one of these classes uses XML attributes and still the JSON strings produced contain the '@' prefix for attributes. I thought that sub-classing would automatically register the new provider with Jersey. But it seems that the new provider is not registered. Could you please help me with that?

Posted by Kareem on January 01, 2010 at 02:57 AM CET #

I have to agree and I will come back to follow you more.

Posted by burton james furniture on January 21, 2010 at 02:15 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Jakub Podlesak

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today