Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson handling Wrapped elements

Tags:

java

json

jackson

I'm parsing the response from last.fm API. But it seems that they used some wrapper for some of the responses, which is causing a bit of a pain. To put an example:

 {
   "artists":{
      "artist":[
         {
            "name":"Coldplay",
            "playcount":"816763",
            "listeners":"120815",
            "mbid":"cc197bad-dc9c-440d-a5b5-d52ba2e14234",
            "url":"http:\/\/www.last.fm\/music\/Coldplay",
            "streamable":"1"
         },
         {
            "name":"Radiohead",
            "playcount":"846668",
            "listeners":"99135",
            "mbid":"a74b1b7f-71a5-4011-9441-d0b5e4122711",
            "url":"http:\/\/www.last.fm\/music\/Radiohead",
            "streamable":"1"
         }
      ],
      "@attr":{
         "page":"1",
         "perPage":"2",
         "totalPages":"500",
         "total":"1000"
      }
   }
}

Not only the response is wrapped in the artists object, but the array of object has also an object wrapper.

So a wrapper class like:

public class LastFMArtistWrapper {
    public List<Artist> artists;

}

Would not work. I worked around this, creating two wrapper classes, but this looks really ugly. Is there any way we can use something like the @XMLElementWrapper in Jackson?

like image 279
Vinicius Carvalho Avatar asked May 26 '12 05:05

Vinicius Carvalho


People also ask

What does @JsonProperty annotation do?

@JsonProperty is used to mark non-standard getter/setter method to be used with respect to json property.

Does Jackson use JAXB?

With XML module Jackson provides support for JAXB (javax. xml. bind) annotations as an alternative to native Jackson annotations, so it is possible to reuse existing data beans that are created with JAXB to read and write XMLs.

What is @JsonAlias?

The @JsonAlias annotation can define one or more alternate names for the attributes accepted during the deserialization, setting the JSON data to a Java object. But when serializing, i.e. getting JSON from a Java object, only the actual logical property name is used instead of the alias.

What does JsonUnwrapped do?

JsonUnwrapped is used to indicate that a property should be serialized unwrapped, i.e. the target property will not be serialized as JSON object but its properties will be serialized as flattened properties of its containing Object.


1 Answers

The JSON response you are getting back from the provider is a serialized representation of a hierarchy of different objects, but from your description, it sounds like you really only need to use and work with a specific subset of this representation, the collection of artists.

One solution of mirroring this representation involves creating the same hierarchy of Java classes, which creates extra overhead in the form of unneeded classes. From what I understand, this is what you wish to avoid.

The org.json project created a generic JSONObject class, which represents a single, generic key/value pair in a larger JSON representation. A JSONObject can contain other JSONObjects and JSONArrays, mirroring the representation without the extra overhead of maintaining and writing extra classes.

Thus, these two objects can be reused throughout multiple layers of hierarchy in a JSON representation, without requiring you to replicate the structure. Here is an example of how you could proceed:

// jsonText is the string representation of your JSON
JSONObject jsonObjectWrapper = new JSONObject(jsonText);  

// get the "artists" object
JSONObject jsonArtists = jsonObjectWrapper.get("artists");

// get the array and pass it to Jackson's ObjectMapper, using TypeReference
  // to deserialize the JSON ArrayList to a Java ArrayList.
List<Artist> artists = objectMapper.readValue(
        jsonObjectWrapper.getString("artist"),
            new TypeReference<ArrayList<Artist>>() { });

Using the above method, you cut out the extra overhead of having to write extra layers of POJO objects that do nothing but add unnecessary clutter.

TestCollectionDeserialization contains some examples of the readValue method when working with collections and may be helpful.

like image 139
jmort253 Avatar answered Oct 01 '22 06:10

jmort253