Jackson is a simple lightweight API to convert Java Objects to JSON and vice-versa.
I do not have statistics to vouch for it being the best and fastest, nevertheless it is very easy to learn and implement.
Here I would like to explore a few common ways in which Jackson API is used. It is not a complete reference, but could serve as a tutorial. The layout is broken as follows
ObjectMapper is our guy to convert a Java object to JSON.
Jackson works on POJOs converting their data to JSON.
Serialization is done as
This will serialize every field with its field name. See the example below.
We have a POJO called Content that has two properties namely title and content.
Now, its time to test our code.
The JSON (formatted from JSON lint)response is
What we observe here is that the property names in Java Object (title, content and comment) have become field names in JSON. (Allow me to call java instance variable as 'property' and JSON key as 'field' for simplicity)
Note: Jackson uses getters to create field names.
Or
Note: The @JsonProperty annotation can be used both on property and on getter.
I personally like to put the annotation over property itself.
Note: The @JsonIgnore annotation can be used both on property and on getter.
If we have multiple properties we wish to ignore, then we can do the following
Note: The @JsonIgnoreProperties annotation can be used only on a class.
Object mapper alone cannot do the trick. To de-serialize a JSON, it needs a constructor. And since all it gets is strings from JSON, it needs to know where each string fits in constructor. So we need to modify the constructor of POJO - Content.java
Each constructor argument is annotated with @JsonProperty indicating the field it maps to in JSON.
TypeReference is a special parameter whose instance has type reference of the object we wish the JSON to be translated to. It is used as
I do not have statistics to vouch for it being the best and fastest, nevertheless it is very easy to learn and implement.
Here I would like to explore a few common ways in which Jackson API is used. It is not a complete reference, but could serve as a tutorial. The layout is broken as follows
Table of Content
- Setup and Initialization
- Java Object to JSON
- Using different field name
- Ignoring properties
- Ignoring a bunch of properties
- JSON to Java Object
- Using different field name
- Sub classes
- Ignoring parent property
- Associations
- Other configurations
- Ignoring null properties
- Dates
- Unknown properties
- Other tricks
- Strings as raw json
- Conclusion
Setup and Initialization
The first step would be to download Jackson API and integrating to build path. The API Jars can be downloaded at Jackson download page. Yes, you need to download all the 3 JARs - core, mapper and annotations.
The conversion revolves around org.codehaus.jackson.map.ObjectMapper class. This class is responsible to convert Object to JSON and vice versa.
The only thing we need to do here is - instantiate this mapper object.
import com.fasterxml.jackson.databind.ObjectMapper; public class JsonUtils { private final static ObjectMapper mapper; static { mapper = new ObjectMapper(); } }
Java Object to Json
Jackson works on POJOs converting their data to JSON.
Serialization is done as
// Here object is the one we wish to serialize
String serializedObject = mapper.writeValueAsString(object)
This will serialize every field with its field name. See the example below.
We have a POJO called Content that has two properties namely title and content.
public class Content { private final String title; private final String content; private final String comment; public Content(String title, String content, String comment) { this.title = title; this.content = content; this.comment = comment; } // Getters and Setters }Now we need to convert this object to json using our ObjectMapper. So we update JsonUtils class.
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonUtils { private final static ObjectMapper mapper; static { mapper = new ObjectMapper(); } public static String serialize(Object object) { try { return mapper.writeValueAsString(object); } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } }
Now, its time to test our code.
public class TestSerialization { public static void main(String args[]) { Content[] contents = new Content[] { new Content("title 1", "content 1", "comment 1"), new Content("title 2", "content 2", "comment 2"), new Content("title 3", "content 3", "comment 3") }; System.out.println(JsonUtils.serialize(contents)); } }
The JSON (formatted from JSON lint)response is
[ { "title": "title 1", "content": "content 1", "comment": "comment 1" }, { "title": "title 2", "content": "content 2", "comment": "comment 2" }, { "title": "title 3", "content": "content 3", "comment": "comment 3" } ]
What we observe here is that the property names in Java Object (title, content and comment) have become field names in JSON. (Allow me to call java instance variable as 'property' and JSON key as 'field' for simplicity)
Note: Jackson uses getters to create field names.
Using different field name
Sometimes we may wish to use another name for the JSON field. There are 3 ways in which we can do it
- Change the property name
- Change the getter method name (because Jackson uses getter to make field name)
- Use annotation
@JsonProperty("header") private final String title;
Or
@JsonProperty("header") public String getTitle() { return title; }The new field name is passed as @JsonProperty annotation parameter.
Note: The @JsonProperty annotation can be used both on property and on getter.
I personally like to put the annotation over property itself.
Ignoring properties
You may sometimes be in a situation where you wouldn't like to serialize a property into JSON field. Let's say we want to ignore the comment field. So this is how we do it.@JsonIgnore private final String comment;
Note: The @JsonIgnore annotation can be used both on property and on getter.
If we have multiple properties we wish to ignore, then we can do the following
@JsonIgnoreProperties({"content", "comment"}) public class Content { ... }
Note: The @JsonIgnoreProperties annotation can be used only on a class.
Json to Java object
ObjectMapper.java is responsible to decode JSON string into our objects. And this is how its done
I would add this method to the JsonUtil.java.import com.fasterxml.jackson.core.type.TypeReference; @SuppressWarnings("unchecked") public staticT extractObjectFromJson(String jsonText, TypeReference type) { try { return (T) mapper.readValue(jsonText, type); } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }
Object mapper alone cannot do the trick. To de-serialize a JSON, it needs a constructor. And since all it gets is strings from JSON, it needs to know where each string fits in constructor. So we need to modify the constructor of POJO - Content.java
public Content(@JsonProperty("header") String title, @JsonProperty("content") String content, @JsonProperty("comment") String comment) { this.title = title; this.content = content; this.comment = comment; }
Each constructor argument is annotated with @JsonProperty indicating the field it maps to in JSON.
TypeReference is a special parameter whose instance has type reference of the object we wish the JSON to be translated to. It is used as
List<Content> contentsFromJson = JsonUtils.extractObjectFromJson(serializedContent,
new TypeReference<List<Content>>() {
});
Using different field name (De-searilizing JSON)
As expected, we need to provided a proper field name with @JsonProperty in the constructor.
Sub classes
Using sub classes with Jackson is pretty easy. All you need to do is - sit back and relax. The following Object AdvancedContent.java is deserialized as belowpublic class AdvancedContent extends Content { private final String subContent; public AdvancedContent(@JsonProperty("header") String title, @JsonProperty("content") String content, @JsonProperty("subContent") String subContent, @JsonProperty("comment") String comment) { super(title, content, comment); this.subContent = subContent; } public String getSubContent() { return subContent; } }
And the JSON created is
{ "header": "title 4", "content": "content 4", "subContent": "sub content 4", "comment": "comment 4" }
See, the parent fields are automatically available on serialization. On de-serialization too, the parent fields will be used.
To ignore a property of parent class, use @JsonIgnoreProperties.
Associations
When an object is build of multiple other objects, that is an association. And it is simple to work with associations. Even String objects in POJO are associated to create Content object. And they are serialized and de-serialized without any special attention.
Try out yourself. And use @JsonIgnore, @JsonProperty annotations as need be.
Other configurations
Jackson can be configured using the ObjectMapper itself. Below we shall see a few common configurations.
Ignoring null properties
Many a times our objects are not full - some of their properties are null. We do not want null appearing all over the JSON right?
mapper.setSerializationInclusion(Include.NON_NULL);
Dates
Date objects are often toughest to work with. And they can be serialized in multiple ways. So here is how we can ask Jackson to serialize dates for us.
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
Unknown properties
Many a times we get unknown properties in JSON. So either we ignore them and go ahead, or we fail the parsing. Default is to go on. But certain scenarios warrant us to fail. And this is how we fail
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
There are many other configurations we may need. Here is a documentation of a few of them.
Other tricks
Strings as raw json
There are a few scenarios where our object itself contains a JSON object already (obviously as a String). So when we let Jackson serialize them, it messes with them.
The quotes are messed up. E.g. below
public class Content { @JsonProperty("header") private final String title; private final String jsonContent; public Content(@JsonProperty("header") String title, @JsonProperty("jsonContent") String jsonContent) { this.title = title; this.jsonContent = jsonContent; } public String getTitle() { return title; } public String getJsonContent() { return jsonContent; } }And the converted JSON would be
{ "header": "title 4", "jsonContent": "{\"prop1\":\"val-prop-1\",\"prop2\":\"val-prop-2\"}" }
We have an annotation to rescue. We annotate the jsonContent as below
@JsonRawValue
private final String jsonContent;
And the response magically changes to
{ "header": "title 4", "jsonContent": { "prop1": "val-prop-1", "prop2": "val-prop-2" } }
Conclusion
It is impossible to cover all the possible scenarios/tricks we can do with Jackson, but this was a shot to get us started.I hope this article helps you in achieving your goal.
Please do reach me at harsh.curse@gmail.com or post a comment if I went wrong somewhere or if there is something I should cover as a part of this article.
Thanks,
Harsh
Thanks for the useful article.
ReplyDelete
ReplyDeleteHi there everyone, I have come across almost all the web development sites. However, your website is far better than other in form of content, tools and easiness of using website. Since I am a developer, I am always looking forward to make people aware of web development tools. I can help you people out by introducing you to range of json tools. Here is the link jsononline
Thank you Perry. I really like https://jsononline.net/. It is neat, and has very good tools that I would love to use for my development.
DeleteGood web site you have got here.. It’s hard to find quality writing like yours nowadays. Please see does starbucks take ebt
ReplyDeletePortable and wireless, Kindle is the most popular online book reading device. Amazon is a famous American corporation that produces it. In 2007, the first Kindle was released. Since its release, the Amazon company's Kindle has made its way into the hearts of multiple users, which has made it the world's most renowned and celebrated e-reading platform. Read more: https://crawlinfo.com/services/how-to-reach-kindle-support-number/
ReplyDeletepapa
ReplyDelete