Jackson Tree Model examples

Jackson’s Tree Model provides a flexible way to work with JSON data compared to the data-binding method. The Tree Model works well when the JSON data or JSON’s schema is unknown until runtime or the JSON structure does not map properly to Java classes.

This article shows how to use Jackson’s Tree Model JsonNode and ObjectNode to parse, access, add, modify, remove, and generate JSON.

Table of contents:

P.S Tested with Jackson 2.17.0

1. Download Jackson

Declares jackson-databind at pom.xml.

pom.xml

  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.0</version>
  </dependency>

2. Accessing the JSON using JsonNode

The following example shows how to use Jackson TreeModel to traversing or accessing the JSON data.

Example JSON data.

tree/user.json

{
  "id": 1,
  "name": {
    "first": "Yong",
    "last": "Mook Kim"
  },
  "contact": [
    {
      "type": "phone/home",
      "ref": "111-111-1234"
    },
    {
      "type": "phone/work",
      "ref": "222-222-2222"
    }
  ]
}
JacksonTreeModelExample1.java

package com.mkyong.json.jackson.treemodel;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class JacksonTreeModelExample1 {

    public static void main(String[] args) {

        String json = """
                {
                  "id": 1,
                  "name": {
                    "first": "Yong",
                    "last": "Mook Kim"
                  },
                  "contact": [
                    {
                      "type": "phone/home",
                      "ref": "111-111-1234"
                    },
                    {
                      "type": "phone/work",
                      "ref": "222-222-2222"
                    }
                  ]
                }
                """;
        try {

            ObjectMapper mapper = new ObjectMapper();

            // read from a json file
            //JsonNode root = mapper.readTree(new File("tree/user.json"));

            // read from a json string
            JsonNode root = mapper.readTree(json);

            // Get id
            long id = root.path("id").asLong();
            System.out.println("id : " + id);

            // Get Name
            JsonNode nameNode = root.path("name");
            if (!nameNode.isMissingNode()) {        // if "name" node exists?
                System.out.println("firstName : " + nameNode.path("first").asText());
                System.out.println("middleName : " + nameNode.path("middle").asText());
                System.out.println("lastName : " + nameNode.path("last").asText());
            }

            // Get Contact
            JsonNode contactNode = root.path("contact");
            if (contactNode.isArray()) {

                System.out.println("Is this node an Array? " + contactNode.isArray());

                for (JsonNode node : contactNode) {
                    String type = node.path("type").asText();
                    String ref = node.path("ref").asText();
                    System.out.println("type : " + type);
                    System.out.println("ref : " + ref);

                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Output


id : 1
firstName : Yong
middleName : 
lastName : Mook Kim
Is this node an Array? true
type : phone/home
ref : 111-111-1234
type : phone/work
ref : 222-222-2222

2. Accessing the JSON Array using JsonNode

The following example shows how Jackson TreeModel can traverse or access the JSON array.

Example of JSON array

tree/user2.json

[
  {
    "id": 1,
    "name": {
      "first": "Yong",
      "last": "Mook Kim"
    },
    "contact": [
      {
        "type": "phone/home",
        "ref": "111-111-1234"
      },
      {
        "type": "phone/work",
        "ref": "222-222-2222"
      }
    ]
  },
  {
    "id": 2,
    "name": {
      "first": "Yong",
      "last": "Zi Lap"
    },
    "contact": [
      {
        "type": "phone/home",
        "ref": "333-333-1234"
      },
      {
        "type": "phone/work",
        "ref": "444-444-4444"
      }
    ]
  }
]

The concept is the same: loop the JSON array:


	JsonNode rootArray = mapper.readTree(new File("c:\\projects\\user2.json"));

	for (JsonNode root : rootArray) {
		// get node like the above example 1
	}
JacksonTreeModelExample2.java

package com.mkyong.json.jackson.treemodel;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample2 {

    public static void main(String[] args) {

        try {

            ObjectMapper mapper = new ObjectMapper();

            JsonNode rootArray = mapper.readTree(new File("tree/user2.json"));

            for (JsonNode root : rootArray) {

                // Get id
                long id = root.path("id").asLong();
                System.out.println("id : " + id);

                // Get Name
                JsonNode nameNode = root.path("name");
                if (!nameNode.isMissingNode()) {        // if "name" node exists?
                    System.out.println("firstName : " + nameNode.path("first").asText());
                    System.out.println("middleName : " + nameNode.path("middle").asText());
                    System.out.println("lastName : " + nameNode.path("last").asText());
                }

                // Get Contact
                JsonNode contactNode = root.path("contact");
                if (contactNode.isArray()) {

                    System.out.println("Is this node an Array? " + contactNode.isArray());

                    for (JsonNode node : contactNode) {
                        String type = node.path("type").asText();
                        String ref = node.path("ref").asText();
                        System.out.println("type : " + type);
                        System.out.println("ref : " + ref);

                    }
                }

            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}

Output


id : 1
firstName : Yong
middleName : 
lastName : Mook Kim
Is this node an Array? true
type : phone/home
ref : 111-111-1234
type : phone/work
ref : 222-222-2222
id : 2
firstName : Yong
middleName : 
lastName : Zi Lap
Is this node an Array? true
type : phone/home
ref : 333-333-1234
type : phone/work
ref : 444-444-4444

3. CRUD JSON using the ObjectNode

The following example shows how to create, update, and remove new JSON nodes.

Example of JSON data.


{
  "id" : 1,
  "name" : {
    "first" : "Yong",
    "last" : "Mook Kim"
  },
  "contact" : [ {
    "type" : "phone/home",
    "ref" : "111-111-1234"
  }, {
    "type" : "phone/work",
    "ref" : "222-222-2222"
  } ]
}

We will modify the above JSON data into the following JSON data.


{
  "id" : 1000,
  "name" : {
    "first" : "Yong",
    "middle" : "M",
    "nickname" : "mkyong"
  },
  "contact" : [ {
    "type" : "phone/home",
    "ref" : "111-111-1234"
  }, {
    "type" : "phone/work",
    "ref" : "222-222-2222"
  }, {
    "type" : "email",
    "ref" : "[email protected]"
  } ],
  "position" : {
    "name" : "Developer",
    "years" : 10
  },
  "games" : [ {
    "name" : "Fall Out 4",
    "price" : 49.9
  }, {
    "name" : "Dark Soul 3",
    "price" : 59.9
  } ]
}

Read the comments for self-explanatory.

JacksonTreeModelExample3.java

package com.mkyong.json.jackson.treemodel;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample3 {

    public static void main(String[] args) {

        try {

            ObjectMapper mapper = new ObjectMapper();

            JsonNode root = mapper.readTree(new File("tree/user.json"));

            // pretty print
            String resultOriginal = mapper
                    .writerWithDefaultPrettyPrinter()
                    .writeValueAsString(root);
            System.out.println("Before Update " + resultOriginal);

            // modifying data
            // 1. Update id to 1000
            ((ObjectNode) root).put("id", 1000L);

            // 2. If middle name is empty , update to M
            ObjectNode nameNode = (ObjectNode) root.path("name");
            if (nameNode.path("middle").asText().isEmpty()) {
                nameNode.put("middle", "M");
            }

            // Adding new data
            // 3. Create a new field in nameNode
            nameNode.put("nickname", "mkyong");

            // remove data
            // 4. Remove last field in nameNode
            nameNode.remove("last");

            // 5. Create a new ObjectNode and add to root
            ObjectNode positionNode = mapper.createObjectNode();
            positionNode.put("name", "Developer");
            positionNode.put("years", 10);
            ((ObjectNode) root).set("position", positionNode);

            // 6. Create a new ArrayNode and add to root
            ArrayNode gamesNode = mapper.createArrayNode();

            ObjectNode game1 = mapper.createObjectNode().objectNode();
            game1.put("name", "Fall Out 4");
            game1.put("price", 49.9);

            ObjectNode game2 = mapper.createObjectNode().objectNode();
            game2.put("name", "Dark Soul 3");
            game2.put("price", 59.9);

            gamesNode.add(game1);
            gamesNode.add(game2);
            ((ObjectNode) root).set("games", gamesNode);

            // 7. Append a new Node to ArrayNode
            ObjectNode email = mapper.createObjectNode();
            email.put("type", "email");
            email.put("ref", "[email protected]");

            JsonNode contactNode = root.path("contact");
            ((ArrayNode) contactNode).add(email);

            String resultUpdate = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);

            System.out.println("After Update " + resultUpdate);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

Output


Before Update {
  "id" : 1,
  "name" : {
    "first" : "Yong",
    "last" : "Mook Kim"
  },
  "contact" : [ {
    "type" : "phone/home",
    "ref" : "111-111-1234"
  }, {
    "type" : "phone/work",
    "ref" : "222-222-2222"
  } ]
}
After Update {
  "id" : 1000,
  "name" : {
    "first" : "Yong",
    "middle" : "M",
    "nickname" : "mkyong"
  },
  "contact" : [ {
    "type" : "phone/home",
    "ref" : "111-111-1234"
  }, {
    "type" : "phone/work",
    "ref" : "222-222-2222"
  }, {
    "type" : "email",
    "ref" : "[email protected]"
  } ],
  "position" : {
    "name" : "Developer",
    "years" : 10
  },
  "games" : [ {
    "name" : "Fall Out 4",
    "price" : 49.9
  }, {
    "name" : "Dark Soul 3",
    "price" : 59.9
  } ]
}

4. Download Source Code

$ git clone https://github.com/mkyong/java-json

$ cd jackson/treemodel

5. References

mkyong

Founder of Mkyong.com, passionate Java and open-source technologies. If you enjoy my tutorials, consider making a donation to these charities.

18 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
bindiya
6 years ago

How to update the Contact array.
For Ex: Change :
“contact” : [ {
“type” : “phone/home”,
“ref” : “111-111-1234”
}
to:
“contact” : [ {
“type” : “phone/home”,
“ref” : “000-111-1234”
}

Nikhil
8 years ago

Hi, I m regular reader, and its very helpful website. I have a query on Jackson JSON string to Object conversion. Everything works perfectly fine except the following. JSON string is having a node like “urn:ietf:params:scim:schemas:extension:enterprise:2.0:User”.

How can I map it into a Java class?

Code snippet:

Sample JSON:

{
“schemas”: [ “urn:ietf:params:scim:schemas:core:2.0:User”, “urn:ietf:params:scim:schemas:extension:enterprise:2.0:User”],
“name”: {
“formatted”: “Ms. Barbara J Jensen III”,
“familyName”: “Jensen”,
“givenName”: “Barbara”,
“middleName”: “Jane”,
“honorificPrefix”: “Ms.”,
“honorificSuffix”: “III”
},
“emails”: [
{
“value”: “[email protected]”,
“type”: “work”,
“primary”: true
},
{
“value”: “[email protected]”,
“type”: “home”
}
],
“id”: “2819c223-7f76-453a-919d-413861904646”,
“externalId”: “701984”,

“urn:ietf:params:scim:schemas:extension:enterprise:2.0:User”: {
“employeeNumber”: “701984”,
“costCenter”: “4130”,
“organization”: “Universal Studios”,
“division”: “Theme Park”,
“department”: “Tour Operations”,
“manager”: {
“value”: “26118915-6090-4610-87e4-49d8ca9f808d”,
“$ref”: “../Users/26118915-6090-4610-87e4-49d8ca9f808d”,
“displayName”: “John Smith”
}
}

}

SCIMUser scimUser = mapper.readValue(jsondata, SCIMUser.class);

public class SCIMUser {

private List schemas;
private Map name;
private List<Map> emails;
private String id;
private String externalId;

// what to do with “urn:ietf:params:scim:schemas:extension:enterprise:2.0:User” ?

… then I have all setters-getters here …
}

I hope you got my question. Kindly suggest.

Regards,
Nik

tabish
5 years ago

do we have to rewrite whole root, while doing little CRUD operations?

felipe
8 years ago

it was very usefully!!

alan2306
9 years ago

Why not just use ObjectNode as the root node in “3. TreeModel CRUD Example”? It would avoid all the casts no?

VXBA
9 years ago

I have two class:
class A {
int id;
String name;
}

class B {
String property1;
String property2;
String property3;
}

– A extends B

– Response:
{
“property1”: “value1”,
“property2”: “value2”,
“property3”: “value3”
“id”:1,
“name”: ‘my name”
}

I want to display as below
{
id:1,
“name”: ‘my name’,
“property1”: “value1”,
“property2”: “value2”,
“property3”: “value3”

}
How to do that?
Thank All!

Jigs N
9 years ago

Hi, How will this work if I do not know the keyName (keys) or the size (level of nesting) of the JSON. Can we dynamically get the keys first and then the values? (I need to collect the key and values in an XL for further processing)

Kumar
10 years ago

Is there a way to traverse and drop the element from nested JSON?

Rames
12 years ago

Make some thing with object []

mkyong
10 years ago
Reply to  Rames

Article is updated to Jackson 2.6.3, with a lot new examples. Refer to example 2 . Just loop the nodes.

IranianCyberArmy
12 years ago

how to change the “name”
“name” : “updated name”
change “name” to “myname”

mkyong
10 years ago

Refer to example 3, how to create or update a JsonNode

Brandon Anderson
12 years ago

thank you this is very useful!, but I still need help 🙁
the jason file i need to modify is like this:

{
“profiles”: {
“AmiliousPixelmon”: {
“authentication”: {
“username”: “X_Amilious_X”,
“accessToken”: “ad15f3240baf4a31b447d2f045358855”,
“uuid”: “c08641daa63c4da485e7ba67f3688185”,
“displayName”: “X_Amilious_X”
},
“name”: “AmiliousPixelmon”,
“gameDir”: “C:\\Users\\School\\AppData\\Roaming\\.minecraft”,
“lastVersionId”: “AmiliousPixelmon”
},
“New Profile”: {
“name”: “New Profile”,
“gameDir”: “C:\\Users\\School\\AppData\\Roaming\\.minecraft”,
“lastVersionId”: “AmiliousPixelmon”,
“allowedReleaseTypes”: [
“snapshot”,
“release”
]
},
“New Profile?”: {
“name”: “New Profile?”,
“gameDir”: “C:\\Users\\School\\AppData\\Roaming\\.minecraft”,
“lastVersionId”: “AmiliousPixelmon1.5.2”,
“allowedReleaseTypes”: [
“release”,
“snapshot”
]
},
“(Default)”: {
“authentication”: {
“username”: “X_Amilious_X”,
“accessToken”: “e719148cdbeb4545ae53a87eb79f1027”,
“uuid”: “c08641daa63c4da485e7ba67f3688185”,
“displayName”: “X_Amilious_X”
},
“name”: “(Default)”
}
},
“selectedProfile”: “New Profile”,
“clientToken”: “0b02dff0-834e-4c08-b469-e13bb2832597”
}

and what I want to do is read all the info into a multidimensional array check if a profile exists and if it does not create it. Can you help me????

mkyong
10 years ago

Refer to example 3 above – TreeModel CRUD Example

asfandyar
11 years ago

Hey Brandon, Did you figure it out how to do this.

Maria
13 years ago

Very useful! Thank you!

mkyong
10 years ago
Reply to  Maria

Welcome. Article is fully updated to Jackson 2.6.3