使用 JSON String 更新现有的对象
ObjectMapper
的以下方法创建了 ObjectReader
实例,该实例可在反序列化传入 JSON 的同时更新现有对象。
ObjectReader readerForUpdating(Object valueToUpdate)
ObjectReader
有各种方法来读取输入 JSON 并返回更新后的对象。比如
public <T> T readValue(String jsonInput) throws IOException
Examples
更新现有的 POJO
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;
...
}
public class ExampleMain {
public static void main(String[] args) throws JsonProcessingException {
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 om = new ObjectMapper();
ObjectReader objectReader = om.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()));
}
}
从输出中可以看到,Employee 的字段已经使用输入的 JSON 进行了更新,只有传入的 JSON 中不存在字段保持了原样。
对于 address 字段(嵌套POJO),它已经被一个新的实例完全替换。且原来的 Address 实例的字段没有发生变化。新的实例完全按照 JSON 中的内容构建,没有填充原实例的内容。从 zipCode=null 而不是 zipCode=23456,能够看出。
同样,正如 hash code 所看到的,objectReader.readValue()
没有返回 Employee 的新实例,而是使用传入JSON 的值更新了现有实例。但对于嵌套 POJO 字段,将创建一个新实例。
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: 2059904228
existing nested object 'address' hashCode: 1824835605
before update address: Address{street='101 Blue Dr', city='SunBridge', zipCode=23456}
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: 2059904228
updated nested object 'address': Address{street='101 Blue Dr', city='White Smoke', zipCode=null}
updated nested object 'address' hashCode: 530737374
after update address: Address{street='101 Blue Dr', city='SunBridge', zipCode=23456}
更新现有的 Map
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")));
}
}
对于嵌套的 Map,除了缺少 zipCode 外,其他值都使用输入的 JSON 更新了。嵌套的 Map 实例没有被新实例替换。
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: 2052915500
existing nested map hash code: 998351292
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: 2052915500
updated nested map hash code: 998351292
数组不会被更新
原有的数组不会被更新。而是创建新的数组并将原有数组的元素与 JSON 中的内容进行 merge。
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));
System.out.println("existing array: " + Arrays.toString(existingArray));
System.out.println("existing array hashCode: " + System.identityHashCode(existingArray));
}
}
input json: ["apple", "banana" ]
existing array: [avocado, mango, cherries]
existing array hashCode: 940553268
updated array: [avocado, mango, cherries, apple, banana]
updated array hashCode: 707976812
existing array: [avocado, mango, cherries]
existing array hashCode: 940553268
更新现有的 Collection
集合会被更新
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: 1720435669
updated list: [avocado, mango, cherries, apple, banana]
updated list hashCode: 1720435669
原文链接
Jackson JSON - Updating Existing objects with JSON input during Deserialization