Aug 152016
 
Share...Tweet about this on TwitterShare on FacebookShare on Google+Share on StumbleUponShare on LinkedInPin on PinterestShare on TumblrShare on RedditDigg this

Let’s learn the basics of Jackson Data binding API in this post. You will also get to know the steps of using this API in Java web development. Read this post and share your thoughts at the end.

Technology

Jackson data binding is the Java API to serialize the Java Object to JSON (JavaScript Object Notation) format, and de-serialize the JSON string to Java Object. This API is used to send JSON string from Restful Rest based Services. It is most widely used format which is used to transfer the data from server to client. It is the light weight format than previously used XML format.

At present there are two Jackson Data Providers are available.

  1. Codenhaus Jackson Library
  2. FasterXML Jackson Library

Codenhaus is the older version of Faster Jackson, so it is better to use Faster XML Library.
Main Components involved in Jackson Data Binding:

  1. Jackson-Core: it has core library which provides the low level parser, generators and it has abstract Java file for different formats like XML, CSV. It also contains default Jackson Handlers for different types like Collection, Maps etc…
  2. Jackson-Annotations: It provides the various annotations which will be used handler to customize the serialization and de-serialization process.
  3. Jackson-Databind: It provides JSON specific data processor, it uses Jackson Annotations for configuration.

For Maven add below dependencies:

<properties>
    <jackson.versioxn>2.7.4</jackson.version>
</properties>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${jackson.version}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${jackson-annotations-version}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>

For Gradle:

compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.7.4'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.7.4'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.7.4'

It is better to choose all dependencies with same version, unless we need to check the mentioned core version is compact ability with jackson-annotations and jackson-databinding versions.

If we are not using any build systems then we can download maven central repository and add to classpath.

  • http://central.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.7.4/jackson-core-2.7.4.jar
  • http://central.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.7.4/jackson-databind-2.7.4.jar
  • http://central.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.7.4/jackson-annotations-2.7.4.jar

Examples:
Serializing the Java Object:

POJO class we are using:

public class User 
{
    public int id;
    public String name;
    public User(int id, String name){
        super();
        this.id = id;
        this.name = name;
    }
 
    public User() {}
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Main class:

public static void main(String[] args) throws JsonProcessingException
{
    User user = new User(2, "sample");
    ObjectMapper mapper = new ObjectMapper();
    String jsonString = mapper.writeValueAsString(user);
    System.out.println(jsonString);
}

We created an object user and we want to serialize this object, jackson-databind jar provides ObjectMapper which will used to serialize and de-serialize the java objects.
mapper.writeValueAsString method will use jackson annotations (if specified) to customize it, here we haven`t specified so it will use object property has key.

The output will be

{"id":2,"name":"sample"}

Customizing JSON Keys:
We want to customize the name property, instead of name we need userName in JSON output, and then we can annotations provided by Jackson-Annotation library.

1) We can annotate the name property with @JsonProperty("userName") so that key value is overwrite with value mentioned in JsonProperty annotation.

The POJO looks like this:

public int id;
@JsonProperty("userName")
public String name;
//Constructors and getter-setter

The output will be:

{"id":2,"userName":"sample"}

The same way we can customize to any property in given object that we want to serialize to String.

2) We can annotate the getter methods of property (es) with @JsonGetter we can specify the value, it will used as key in JSON.

POJO looks like this after modifications:

public class User {
    private int id;
    private String name;

    public User(int id, String name)
    {
        super();
        this.id = id;
        this.name = name;
    }

    public User() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @JsonGetter("userName")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

The output will be same above:

{"id":2,"userName":"sample"}

Key Order

If we need some specific order for property(es) in object then we can use @JsonPropertyOrder at class level, we need to pass the order in which you are expecting.
Suppose if weed userName as first key then we can use @JsonPropertyOrder({"name”, id"}) at class level so that userName will come first.

After modification POJO looks like this:

@JsonPropertyOrder({"name","id"})
public class User {
    public int id;
    
    @JsonProperty("userName")
    public String name;
    // constructors, getter and setters
}

If we run the same main class again the output will be

{"userName":"sample","id":2}

Ignoring Object property(es):
If we want to some of the properties in Object, then we can add @JsonIgnore at each of field.
Instead of adding at each property field, we can add @JsonIgnoreProperties at class level, we can specify the all properties that we want to ignore.
If we want to ignore name property then the POJO will look like this:

public class User {
    public int id;
    
    @JsonIgnore
    public String name;
    
    //constructors and getter-setters
    }

Or

@JsonIgnoreProperties({"name"})
public class User {
    public int id;
    public String name;
}

The output will be:

{"id":2}

Ignoring Types

If we want to ignore some user-defined class property(es) in serializing the object then we can use @JsonIgnoreType on which you want to ignore.
Our User POJO contains Address(user-defined) class and we want to ignore all Address type of property.

public class User {

    @JsonIgnoreType
    public static class Address {
        private String houseNumber;
        private String zipCode;
        private String city;
        private String country;
        //constructors and getter-setters
    }

    private int id;
    @JsonProperty("userName")
    private String name;
    private Address address;
    //constructors and getter-setters
}

We can add JsonIgnoreType at class level that we want to ignore.
Modified Main class:

public static void main(String[] args) throws JsonProcessingException {
    User user = new User(2, "sample");
    Address address = new Address();
    address.setHouseNumber("flat no.108");
    address.setCity("hyderabad");
    address.setCountry("india");
    address.setZipCode("500072");
    user.setAddress(address);
    ObjectMapper mapper = new ObjectMapper();
    String jsonString = mapper.writeValueAsString(user);
    System.out.println(jsonString);
}

Output of the main program will be:

{"id":2,"userName":"sample"}

Formatting Objects

If the User object contain Date type object then, if you try to serialize it, it convert into long value and it will serialize, if we want to serialize to human readable format then we need to annotate the field with @JsonFormat

So that it will format date value to specified type.

Eg: updated User class:

public class User {
    
    private int id;
    private String name;
    @JsonFormat(shape=Shape.STRING, pattern="yyyy-MM-dd HH:mm:sss")
    private Date date = new Date();
    //constructors and getter-setters
    }

ObjectMapper class will convert the date property to string contains the value as specified the pattern.
If you run the main class the output will be

{"id":2,"date":"2016-06-14 13:17:045","userName":"sample"}

Filtering JSON Results

If we want to filter some properties based on condition on Object, then we can use @JsonFilter on a class level.

@JsonFilter("myFilter")
public class User {
    private int id;
    @Ignore
    private String name;
    @JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:sss")
    private Date date;
    private String type;
    // constructors and setter-getters
}

And ignore annotation will look this:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ignore { }

And we need to provide filterProvider to ObjectMapper.
Eg:

SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("myFilter", new MyFilter());
mapper.setFilterProvider(filterProvider);

And MyFilter class look like this:

public class MyFilter extends SimpleBeanPropertyFilter {
    @Override
    public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
    throws Exception
    {
        if (include(writer))
        {
            String propertyName = writer.getName();
            Ignore ignore = writer.findAnnotation(Ignore.class);
            if ("type".equalsIgnoreCase(propertyName))
            {
                User user = (User) pojo;
                if ("simple".equalsIgnoreCase(user.getType()))
                {
                    writer.serializeAsField(pojo, jgen, provider);
                }
            }
            else if(ignore ==null)
            {
                writer.serializeAsField(pojo, jgen, provider);
            }
        }
    }

    @Override
    protected boolean include(BeanPropertyWriter writer) {
        return true;
    }

    @Override
    protected boolean include(PropertyWriter writer) {
        return true;
    }
}

serializeAsField method we can customize based on which conditions we want to serialize the property, the above method will serialize only if the fields doesn`t contain Ignore Annotation and if type field value is simple then only it will serialize.

Like we can control the serialization of the object using filter.

Excluding NULL and EMPTY Values

@JsonInclude: Annotation used to indicate when value of the annotated property, or all properties of the annotated class, is to be serialized. Without annotation property values are always included, but by using this annotation one can specify simple exclusion rules to reduce amount of properties to write out.
It has two attributes.
Value: this attribute will serialize based on attribute value, if will contain from Include Enum value.

Possible values are:

  • ALWAYS: it will be included always, irrespective of the value.
  • NON_NULL: it will be included only when value is not null (having some value)
  • NON_ABSENT: “absent” value of a referential type (like Java 8 ‘Optional’, or that is, something that would not deference to a non-null value.
  • NON_EMPTY: if the value is non-empty and default values for Java types. (like “0” for integer, “false” for boolean type,”” for string type.
    Eg:

    @JsonInclude(content=Include.NON_EMPTY, value=Include.NON_EMPTY)
    
     private String type;

So if type is value non-empty then only type property is included otherwise not.

This post is intended by Java web development experts to make you learn about the concept of Jackson data binding API. They have also shared the steps for using this API in Java project. If you have any question in your mind, ask freely. The experts will answer your question soon.

Conclusion

It’s the widely used API for converting Java Object to JSON String and JSON String to Java Object using ObjectWrapper. It also provides the various annotations for customizing the return value from ObjectMapper. Using SimpleBeanPropertyFilter we can customize the way to serialize the each property present in Java Object.

    Share...Tweet about this on TwitterShare on FacebookShare on Google+Share on StumbleUponShare on LinkedInPin on PinterestShare on TumblrShare on RedditDigg this

    James Warner is working as content developer in a reputed java web development company. You can share your thoughts regarding this post with her and suggest some topics. She will pick the interesting one and share her thoughts on the same.

      2 Responses to “How to use Jackson data binding API in Java Web Development”

    1. I do agree with all the ideas you have presented in your post. They’re really convincing and will certainly work. Still, the posts are very short for newbies. Could you please extend them a little from next time?..

    Leave a Reply

    mapes-rosalee@mailxu.com