JSON Bindings
JSON, short for JavaScript Object Notation, is a lightweight data interchange format. It is a text-based, human-readable format for representing simple data structures and associative arrays (called objects).
iBeans support binding JSON data to objects and marshaling Java object to JSON using the Jackson Framework. Jackson uses annotations to describe how data is mapped to a Java object model. For example, lets say we have an JSON file that describes a person. When we receive that JSON data we want to convert it into a Person object. The JSON looks like this-
{
"name":"John Doe",
"dob":"01/01/1970",
"emailAddresses":[
{
"type":"home",
"address":"john.doe@gmail.com"
},
{
"type":"work",
"address":"jdoe@bigco.com"
}
]
}
And we have an object Person we want to create from the JSON data. We use annotations to describe how to perform the mapping. We use the @JsonAutoDetect to say that field member names map directly to JSON field names -
@JsonAutoDetect public class Person { private String name; private String dob; private List<EmailAddress> emailAddresses; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDob() { return dob; } public void setDob(String dob) { this.dob = dob; } public List<EmailAddress> getEmailAddresses() { return emailAddresses; } public void setEmailAddresses(List<EmailAddress> emailAddresses) { this.emailAddresses = emailAddresses; } }
The EmailAddress object that is used in the emailAddresses is just another JavaBean with the @JsonAutoDetect annotation.
At this point iBeans can figure out whether to perform a JSON transforms based on the parameters of the method being called. For example -
@Receive(uri = "jms://people") public void processPerson(Person person) { //tickle him }
Here we would receive the contents of the people.json file above on a JMS queue, iBeans would see that Person.class is an annotated JSON object and that we had received JSON data from the JMS queue and perform the conversion.
Binding transformers can also be used with iBean interfaces, for example we could parse the response from Twitter into a status object -
@Call(uri = "http://www.twitter.com/statuses/update.json") public Status statusesUpdate(@PayloadParam("status") String status) throws CallException;
Global JSON Mapper
Jackson performs mappings through the ObjectMapper. This is an object that can be configured with other configuration about how to serialise data and define mixins that add annotations to objects that you cannot change directly. It is possible to define a global ObjectMapper; a single mapper that will be used for all JSON transforms in your application. This is not required since iBeans will automatically create a mapper for a transformer, but using a global mapper can be useful if you need to configure specific properties on the mapper or use mixins. To create a shared ObjectMapper create a module class that creates the ObjectMapper instance, this example uses Guice -
public class MapperConfigModule extends AbstractGuiceIBeansModule { protected void doConfigure() throws Exception { mapper = new ObjectMapper(); mapper.getSerializationConfig().addMixInAnnotations(Person.class, PersonMixin.class); mapper.getDeserializationConfig().addMixInAnnotations(Person.class, PersonMixin.class); bind(ObjectMapper.class).toInstance(mapper); } }
See Using Guice for more information about modules and dependency injection.
Intercepting JSON Transforms
So far we have discussed how iBeans will perform automatic JSON transforms. Sometimes you may want to intercept the transform, to do this just create a transformer with a method return or param type of your JSON class -
@Transformer(sourceTypes = {InputStream.class})
public Person toPerson(String json, ObjectMapper mapper) throws JAXBException
{
return (Person)mapper.readValue(in, Person.class);
}
The ObjectMapper instance will either be created for you or the global context for you application will be used. One reason for doing this would be to strip out some JSON elements and create objects from a subset of the JSON received. For more information about transforms see the Working with Transformers section.
Add Comment