Close

Jackson JSON - Deep merging with @JsonMerge Annotation

[Updated: Feb 15, 2019, Created: Feb 15, 2019]

In the last tutorial we saw how to update an existing object with JSON input. In case of nested POJO field, Jackson does not update the individual nested fields but replace the entire instance. In other words Jackson only performs updates on scalar fields and not on the object fields. This behavior is also referred as 'shallow merging'.

Starting Jackson 2.9 we can use @JsonMerge annotation on object fields to update nested fields with JSON input. In other words now we are able to selectively perform 'deep merging' by using @JsonMerge.

Example

POJOs

public class Employee {
  private String name;
  private String dept;
  private int salary;
  private String phone;
  @JsonMerge
  private Address address;
    .............
}
public class Address {
  private String street;
  private String city;
  private String zipCode;
    .............
}

Main class

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: 1597462040
existing nested object 'address' hashCode: 1681595665
updated object: Employee{name='Jake', dept='Dev', salary=3000, phone='222-222-222', address=Address{street='101 Blue Dr', city='White Smoke', zipCode=23456}}
updated object hashCode: 1597462040
updated nested object 'address' hashCode: 1681595665

Without @JsonMerge

If we remove @JsonMerge annotation from the 'address' field then output will be:

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: 1076835071
existing nested object 'address' hashCode: 1144648478
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: 1076835071
updated nested object 'address' hashCode: 1254344205

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

@JsonMerge Annotation example Select All Download
  • jackson-json-merge-annotation
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • ExampleMain.java

    See Also