Reading Time: 7 minutes

, short for JavaScript Object Notation, is a lightweight interchange format. It is a text-based, human-readable format for representing simple data structures and associative arrays (called objects).

Many REST services use JSON as the preferred data format (including Tcat Server's REST API). JSON provides a much simpler model for data representation and is widely used in AJAX programing.

iBeans support binding JSON data to objects and marshaling Java objects to JSON using the excellent Jackson Framework.

Jackson uses annotations to describe how data is mapped to a Java object model. For example, lets say we have a 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"
        }
    ]
}

We use annotations to describe how to perform the mapping between the JSON data and the Person object. We use @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 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 getEmailAddresses()
    {
        return emailAddresses;
    }
 
    public void setEmailAddresses(List emailAddresses)
    {
        this.emailAddresses = emailAddresses;
    }
}

The EmailAddress object that is used in the emailAddresses property is just another JavaBean with the @JsonAutoDetect annotation.

At this point, iBeans can figure out whether to perform a JSON transform based on the parameters of the method being called. For example:

latest report
Learn why we are the Leaders in API management and
@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, and 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:

Global JSON Mapper

Jackson performs mappings through the ObjectMapper. You can configure this object to control how data is serialized 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 in iBeans.

Intercepting JSON Transforms

So far we have discussed how iBeans will perform automatic JSON transforms. If you want to intercept the transform, just create a transformer with a method return or parameter type of your JSON class:

@Transformer(sourceTypes = {InputStream.class})
public Person toPerson(String json, ObjectMapper mapper) throws JAXBException
{
    return (Person)mapper.readValue(json, Person.class);
}

The ObjectMapper instance will either be created for you, or the global context for your 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 page.

iBeans provides a way to work with JSON data with automatic Java object binding thanks to Jackson. For most scenarios the developers needs to do nothing more than define their binding objects, and iBeans will figure out the rest. However, it is very easy to customize and control how the JSON data is processed using a custom transformer.