The tutorial is about deserialization(convert JSON to Java object), for serialization(convert Java object to JSON), please visit
To deserialize a JSON string to a Java object, we could use the FasterXML Jackson library in Maven: (Using Gradle please see)
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.4</version> </dependency>
dependencies { implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.9' implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.9' }
For instance, we want to convert the following JSON to Java object:
{"Name":"Sam","age":30,"state":"CA","zip":90008}
Create a com.fasterxml.jackson.databind.ObjectMapper object then call readValue to deserialize the JSON string to a Java object:
public static void main(String args[]) throws Exception { String json = "{\"name\":\"Sam\",\"age\":30,\"state\":\"CA\",\"zip\":90008}"; ObjectMapper objectMapper = new ObjectMapper(); Customer customer = objectMapper.readValue(json, Customer.class); System.out.println("name = " + customer.getName() + ", age = " + customer.getAge() + ", state = " + customer.getState() + ", zip = " + customer.getZip()); }
Customer.java:
public class Customer { private String name; private Integer age; private String state; private Integer zip; // public setter and getter of all the fields }
Output:
name = Sam, age = 30, state = CA, zip = 90008
Customized field name could be used. If a field does not start with lower case letter or have special characters, for instance:
{"@Name!":"Sam","age":30,"state":"CA","zip":90008}
The @JsonProperty annotation could be used to change the field name. The Customer class will look like this:
public class Customer { @JsonProperty("@Name!") private String name; private Integer age; private String state; private Integer zip; // public setter and getter of all the fields }
example:
public static void main(String args[]) throws Exception { String json = "{\"@Name!\":\"Sam\",\"age\":30,\"state\":\"CA\",\"zip\":90008}"; ObjectMapper objectMapper = new ObjectMapper(); Customer customer = objectMapper.readValue(json, Customer.class); System.out.println("name = " + customer.getName() + ", age = " + customer.getAge() + ", state = " + customer.getState() + ", zip = " + customer.getZip()); }
Output:
name = Sam, age = 30, state = CA, zip = 90008
Ignore unknown fields. Having extra fields will cause exception during deserialization. If the JSON is like:
{"name":"Sam","age":30,"state":"CA","zip":90008,"phone":"1234567890"}
example:
public static void main(String args[]) throws Exception { String json = "{\"name\":\"Sam\",\"age\":30,\"state\":\"CA\",\"zip\":90008,\"phone\":\"1234567890\"}"; ObjectMapper objectMapper = new ObjectMapper(); Customer customer = objectMapper.readValue(json, Customer.class); System.out.println("name = " + customer.getName() + ", age = " + customer.getAge() + ", state = " + customer.getState() + ", zip = " + customer.getZip()); }
Exception will be thrown:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "phone"
We could add @JsonIgnoreProperties(ignoreUnknown = true) to the Customer class to ignore unknown fields:
@JsonIgnoreProperties(ignoreUnknown = true) public class Customer { private String name; private Integer age; private String state; private Integer zip; // public setter and getter of all the fields }
No more error:
name = Sam, age = 30, state = CA, zip = 90008
Complete customization of deserialization. For example, if we want the state field to take the value CA in both following situations:
{"name":"Sam","age":30,"state":{"postal":"CA"},"zip":90008}
or:
{"name":"Sam","age":30,"state":"CA","zip":90008}
a custom JsonDeserializer can be used:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; public class CustomerDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { TreeNode tree = jsonParser.readValueAsTree(); String value = tree.toString(); if (value.startsWith("{\"postal\":\"")) { int startPos = "{\"postal\":\"".length(); int endPos = value.lastIndexOf("\"}"); return value.substring(startPos, endPos); } else { return tree.toString().substring(1, tree.toString().length() - 1); } } }
To use the CustomerDeserializer, just annotate the field with it:
public class Customer { private String name; private Integer age; @JsonDeserialize(using = CustomerDeserializer.class) private String state; private Integer zip; // public setter and getter of all the fields }
So both of the following will print the same output:
public static void main(String args[]) throws Exception { String json = "{\"name\":\"Sam\",\"age\":30,\"state\":{\"postal\":\"CA\"},\"zip\":90008}"; ObjectMapper objectMapper = new ObjectMapper(); Customer customer = objectMapper.readValue(json, Customer.class); System.out.println("name = " + customer.getName() + ", age = " + customer.getAge() + ", state = " + customer.getState() + ", zip = " + customer.getZip()); }
or
public static void main(String args[]) throws Exception { String json = "{\"name\":\"Sam\",\"age\":30,\"state\":\"CA\",\"zip\":90008}"; ObjectMapper objectMapper = new ObjectMapper(); Customer customer = objectMapper.readValue(json, Customer.class); System.out.println("name = " + customer.getName() + ", age = " + customer.getAge() + ", state = " + customer.getState() + ", zip = " + customer.getZip()); }
Output:
name = Sam, age = 30, state = CA, zip = 90008
Fields are dynamic. If the number of fields is not fixed, instead of defining all the fields, use @JsonAnySetter to map dynamic fields:
Customer class will be:
public class Customer { private Map<String, String> dynamicFields = new HashMap<>(); @JsonAnySetter public void setDynamicFields(String key, String value) { dynamicFields.put(key, value); } public Map<String, String> getDynamicFields() { return dynamicFields; } }
For following JSON:
{"name":"Sam","age":30,"state":"CA","zip":90008}
example:
public static void main(String args[]) throws Exception { String json = "{\"name\":\"Sam\",\"age\":30,\"state\":\"CA\",\"zip\":90008}"; ObjectMapper objectMapper = new ObjectMapper(); Customer customer = objectMapper.readValue(json, Customer.class); for (String key : customer.getDynamicFields().keySet()) { System.out.println(key + customer.getDynamicFields().get(key)); } }
Output:
zip: 90008
name: Sam
state: CA
age: 30
For following JSON:
{"name":"Sam","gender":"male","state":"CA"}
example:
public static void main(String args[]) throws Exception { String json = "{\"name\":\"Sam\",\"gender\":\"Male\",\"state\":\"CA\"}"; ObjectMapper objectMapper = new ObjectMapper(); Customer customer = objectMapper.readValue(json, Customer.class); for (String key : customer.getDynamicFields().keySet()) { System.out.println(key + customer.getDynamicFields().get(key)); } }
Output:
gender: Male
name: Sam
state: CA