To deserialize a JSON string to a Java object, we could use the FasterXML Jackson library.

Configuration
Java Compilation:
Java Runtime:
Maven:
Java Compilation:
Java Runtime:
Gradle:
JDK 11.0.12
JRE HotSpot 11.0.12
Maven 3.8.4
JDK 11.0.12
JRE HotSpot 11.0.12
Gradle 7.4.2
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