Close

Jackson JSON - Updating Existing objects with JSON input during Deserialization

[Updated: Feb 14, 2019, Created: Feb 13, 2019]

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 Project

Dependencies 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

Updating Existing Objects Examples Select All Download
  • jackson-reader-for-updating
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • ExampleMain.java

    See Also