Using Jackson for Java/JSON Conversion
Jackson is one of the popular Java libraries that makes dealing with JSON easier. In this post, I will share techniques for converting JSON to Java and vice-versa.
The first thing we need to do is download the Jackson jar.
Maven users can simply include this dependency:
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.7</version> </dependency>
Converting Java objects to JSON
Consider a person object with fields first name, last name and ssn. The Java representation of the person is given below:
public class Person { private String firstName; private String lastName; private String ssn; public Person() { } public Person(String firstName, String lastName, String ssn) { this.firstName = firstName; this.lastName = lastName; this.ssn = ssn; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getSsn() { return ssn; } public void setSsn(String ssn) { this.ssn = ssn; } }
Converting a concrete instance of Person class using Jackson involves creating a new ObjectMapper and invoking the writeValueAsString method. The ObjectMapper instance is threadsafe and can be used across multiple threads. The code is shown below:
public void convertJavaToJson() { ObjectMapper objectMapper = new ObjectMapper(); Person person = new Person("John", "Doe", "123-45-6789"); try { String json = objectMapper.writeValueAsString(person); System.out.println(json); } catch(Exception e) { e.printStackTrace(); } }
Upon running the method, the following output is produced:
{“firstName”:”John”,”lastName”:”Doe”,”ssn”:”123-45-6789″}
Jackson automatically converts any nested objects to JSON. For example, lets say each person has an instance of Address class shown below:
public class Address { private String address1; private String city; public String getAddress1() { return address1; } public void setAddress1(String address1) { this.address1 = address1; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } }
The covertJavaToJson method below is converted to add an address and produce JSON:
public void convertJavaToJson() { ObjectMapper objectMapper = new ObjectMapper(); Person person = new Person("John", "Doe", "123-45-6789"); Address address = new Address(); address.setAddress1("Main Street"); address.setCity("Salt Lake City"); person.setAddress(address); try { String json = objectMapper.writeValueAsString(person); System.out.println(json); } catch(Exception e) { e.printStackTrace(); } }
Here is the resulting JSON:
{“firstName”:”John”,”lastName”:”Doe”,”ssn”:”123-45-6789″,”address”:{“address1″:”Main Street”,”city”:”Salt Lake City”}}
It is possible to customize the JSON produced by Jackson. Let’s say we would like to modify the attribute names in the generated JSON to fName and lName. This can be done by simply annotating the Person’s fields with @@JsonProperty. Here is the modified class:
public class Person { @JsonProperty("fName") private String firstName; @JsonProperty("lName") private String lastName; //Other properties and getters/setters }
Here is the generated JSON with new attribute names.
{“ssn”:”123-45-6789″,”address”:{“address1″:”Main Street”,”city”:”Salt Lake City”},”fName”:”John”,”lName”:”Doe”}
It is also possible to filter certain fields from being part of the produced JSON. This is done by annotating the field with @JsonIgnore annotation. In the code we below, we placed the annotation on the Address field:
public class Person { @JsonProperty("fName") private String firstName; @JsonProperty("lName") private String lastName; private String ssn; @JsonIgnore private Address address; // Getters and setters }
Now, when we run the conversion, address will not be included:
{“ssn”:”123-45-6789″,”fName”:”John”,”lName”:”Doe”}
Converting JSON to Java Objects
Let’s say we want to convert the following JSON representation of a person to Person object.
{“firstName”:”Jane”,”lastName”:”Doe”,”ssn”:”456-78-9012″}
In order to perform the conversion, we create an instance of ObjectMapper and invoke the readValue method on it as shown below:
public void convertJSONtoJava() { String personJson = "{\"firstName\":\"Jane\",\"lastName\":\"Doe\",\"ssn\":\"456-78-9012\"}"; ObjectMapper objectMapper = new ObjectMapper(); try { Person person = objectMapper.readValue(personJson, Person.class); System.out.println(person); } catch(Exception e) { e.printStackTrace(); } }
Often times, the Java controllers or Servlets recieve JSON from clients with additional information. For example, the JSON below has an additional action parameter:
{“action”:”modify”,”firstName”:”Jane”,”lastName”:”Doe”,”ssn”:”456-78-9012″}
In those cases, mapping JSON to a Java object will result in UnrecognizedPropertyException:
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field “action” (Class Person), not marked as ignorable
at [Source: java.io.StringReader@16bdb503; line: 1, column: 12] (through reference chain: Person[“action”])
at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267)
These situations can be easily addressed by annotating the Person class with @JsonIgnoreProperties annotation. Here is modified class:
@JsonIgnoreProperties(ignoreUnknown=true) public class Person { // Fields and getters/setters }