The following method of ObjectMapper creates ObjectReader instance that can be used to update an existing Object while deserializing an incoming JSON.
ObjectReader readerForUpdating(Object valueToUpdate)
ObjectReader has various methods for reading an input JSON and returning the updated object. For example:
public <T> T readValue(String jsonInput) throws IOException
Let's understand how to use above method with examples.
Examples
Updating existing POJO instance
public class Employee {
private String name;
private String dept;
private int salary;
private String phone;
private Address address;
.............
}
public class Address {
private String street;
private String city;
private String zipCode;
.............
}
package com.logicbig.example;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import java.io.IOException;
public class ExampleMain {
public static void main(String[] args) throws IOException {
String inputJson = "{\"name\":\"Jake\",\"salary\":3000,"
+ "\"address\":{\"street\":\"101 Blue Dr\",\"city\":\"White Smoke\"}}";
System.out.println("input json: " + inputJson);
Employee existingEmployee = Employee.of("John", "Dev", 1000, "222-222-222",
Address.of("101 Blue Dr", "SunBridge", "23456"));
System.out.println("existing object: " + existingEmployee);
System.out.println("existing object hashCode: " + System.identityHashCode(existingEmployee));
System.out.println("existing nested object 'address' hashCode: " + System
.identityHashCode(existingEmployee.getAddress()));
ObjectMapper objectMapper = new ObjectMapper();
ObjectReader objectReader = objectMapper.readerForUpdating(existingEmployee);
Employee updatedEmployee = objectReader.readValue(inputJson);
System.out.println("updated object: " + updatedEmployee);
System.out.println("updated object hashCode: " + System.identityHashCode(updatedEmployee));
System.out.println("updated nested object 'address' hashCode: " + System
.identityHashCode(updatedEmployee.getAddress()));
}
}
input json: {"name":"Jake","salary":3000,"address":{"street":"101 Blue Dr","city":"White Smoke"}} existing object: Employee{name='John', dept='Dev', salary=1000, phone='222-222-222', address=Address{street='101 Blue Dr', city='SunBridge', zipCode=23456}} existing object hashCode: 2036958521 existing nested object 'address' hashCode: 2017354584 updated object: Employee{name='Jake', dept='Dev', salary=3000, phone='222-222-222', address=Address{street='101 Blue Dr', city='White Smoke', zipCode=null}} updated object hashCode: 2036958521 updated nested object 'address' hashCode: 283717519
As seen in the output, Employee fields have been updated with the input JSON fields, only those fields remained unchanged which were not present in the incoming JSON. In case of the 'address' field (nested POJO), its instance has been completely replaced with a new one. That means the individual fields (address.street, address.city and address.zipCode) were not updated but a new instance has been created, populated with all JSON 'address' fields values and assigned to 'employee#address' field. That can also be seen with address.zipCode=null value instead of keeping the existing zipCode=23456. Also as seen by identity hash codes, no new instance of Employee is returned by objectReader.readValue() but the existing instance is updated with incoming field's value. In case of nested object field 'address', a new instance is created.
Updating existing map instance
An existing map instance can also be updated with an input JSON:
public class ExampleMain2 {
public static void main(String[] args) throws IOException {
String inputJson = "{\"name\":\"Jake\",\"salary\":3000"
+ ",\"address\":{\"street\":\"101 Blue Dr\",\"city\":\"White Smoke\"}}";
System.out.println("input json: " + inputJson);
Map<String, Object> existingMap = new HashMap<>(Map
.of("name", "John", "dept", "Dev", "salary", 1000, "phone", "222-222-222", "address",
new HashMap<>(Map.of("street", "101 Blue Dr", "city", "SunBridge", "zipCode", "23456"))));
System.out.println("existingMap: " + existingMap);
System.out.println("existing map hashCode: " + System.identityHashCode(existingMap));
System.out.println("existing nested map hash code: "+System.identityHashCode(existingMap.get("address")));
ObjectMapper objectMapper = new ObjectMapper();
ObjectReader objectReader = objectMapper.readerForUpdating(existingMap);
Map updatedMap = objectReader.readValue(inputJson);
System.out.println("updated map: " + updatedMap);
System.out.println("updated map hashCode: " + System.identityHashCode(updatedMap));
System.out.println("updated nested map hash code: "+System.identityHashCode(updatedMap.get("address")));
}
} input json: {"name":"Jake","salary":3000,"address":{"street":"101 Blue Dr","city":"White Smoke"}} existingMap: {name=John, address={zipCode=23456, city=SunBridge, street=101 Blue Dr}, dept=Dev, salary=1000, phone=222-222-222} existing map hashCode: 1321640594 existing nested map hash code: 1170794006 updated map: {name=Jake, address={zipCode=23456, city=White Smoke, street=101 Blue Dr}, dept=Dev, salary=3000, phone=222-222-222} updated map hashCode: 1321640594 updated nested map hash code: 1170794006
In case of nested Map, values were individually updated with the input JSON's except for the missing zipCode. The nested Map's instance was not replaced with a new one.
Arrays are not updated
In case of arrays there's no change with the existing array instances i.e. they are not updated/replaced by the new values.
public class ExampleMain3 {
public static void main(String[] args) throws IOException {
String inputJson = "[\"apple\", \"banana\" ]";
System.out.println("input json: " + inputJson);
String[] existingArray = {"avocado", "mango", "cherries"};
System.out.println("existing array: " + Arrays.toString(existingArray));
System.out.println("existing array hashCode: " + System.identityHashCode(existingArray));
ObjectMapper objectMapper = new ObjectMapper();
ObjectReader objectReader = objectMapper.readerForUpdating(existingArray);
String[] updatedArray = objectReader.readValue(inputJson);
System.out.println("updated array: " + Arrays.toString(updatedArray));
System.out.println("updated array hashCode: " + System.identityHashCode(updatedArray));
}
} input json: ["apple", "banana" ] existing array: [avocado, mango, cherries] existing array hashCode: 589446616 updated array: [avocado, mango, cherries] updated array hashCode: 589446616
Updating Collection instance
Collections can be updated with the new incoming JSON values:
public class ExampleMain4 {
public static void main(String[] args) throws IOException {
String inputJson = "[\"apple\", \"banana\" ]";
System.out.println("input json: " + inputJson);
List<String> existingList = new ArrayList<>(List.of("avocado", "mango", "cherries"));
System.out.println("existing list: " + existingList);
System.out.println("existing list hashCode: " + System.identityHashCode(existingList));
ObjectMapper objectMapper = new ObjectMapper();
ObjectReader objectReader = objectMapper.readerForUpdating(existingList);
List<String> updatedList = objectReader.readValue(inputJson);
System.out.println("updated list: " + updatedList);
System.out.println("updated list hashCode: " + System.identityHashCode(updatedList));
}
} input json: ["apple", "banana" ] existing list: [avocado, mango, cherries] existing list hashCode: 1321640594 updated list: [avocado, mango, cherries, apple, banana] updated list hashCode: 1321640594
Example ProjectDependencies and Technologies Used: - jackson-databind 2.9.8: General data-binding functionality for Jackson: works on core streaming API.
- JDK 11
- Maven 3.5.4
|
|