Java JSON traverses nested nodes and populates map

In this example we will see how to use recursion methods in Java to walk over the whole JSON structure. We will use Jackson libraries to get information about the JSON nodes. We will check if the node has other nodes. If so, then we will check them too. In JSON this can be object nodes or array nodes. If we see that the node is a leaf node (node without children), then we will add the path until the node becomes a map key. We will also add the value of the node as a string value to the map. In the end we will print the map.

JSON file example_of_json.json:

[
  {
    "_id": "63e744e785730f8b3eb1dda5",
    "index": 0,
    "isActive": true,
    "balance": "$3,310.75",
    "age": 24,
    "name": "Marsh Velasquez",
    "gender": "male",
    "address": "704 Mill Lane, Dunbar, Iowa, 477",
    "about": "Laboris esse veniam culpa magna sunt consequat culpa elit occaecat non labore id dolore occaecat.",
    "registered": "2018-04-29T02:17:14 -02:00",
    "latitude": 23.617941,
    "longitude": 153.026279,
    "tags": [
      "do",
      "incididunt",
      "sint",
      "qui",
      "nulla"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Mcintosh Montoya"
      },
      {
        "id": 1,
        "name": "Odom Horne"
      }
    ],
    "greeting": "Hello, Marsh Velasquez! You have 6 unread messages.",
    "favoriteFruit": "strawberry"
  },

  {
    "_id": "63e744e73d9ce6418efd7391",
    "index": 1,
    "isActive": false,
    "balance": "$3,917.23",
    "age": 34,
    "name": "Annmarie Gates",
    "gender": "female",
    "address": "662 Franklin Avenue, Sanford, Virgin Islands, 9048",
    "about": "Deserunt reprehenderit ullamco aute pariatur id. Aute sint amet veniam nisi eiusmod dolor est labore.",
    "registered": "2014-10-12T03:12:05 -02:00",
    "latitude": -47.735057,
    "longitude": -88.535544,
    "tags": [
      "sunt",
      "elit",
      "sint",
      "nostrud"
    ],
    "friends": [
      {
        "id": 0,
        "name": "Sloan Snider"
      },
      {
        "id": 1,
        "name": "Elva Rush"
      },
      {
        "id": 2,
        "name": "Alana Hyde"
      }
    ],
    "greeting": "Hello, Annmarie Gates! You have 3 unread messages.",
    "favoriteFruit": "strawberry"
  }
]

We create the Maven project with pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>JSONToFlatMap</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

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

</project>

This is the java class:

package org.example;

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.ValueNode;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class MakeJSONToFlatMap {

    public static void main(String[] args) throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        // We choose to use LinkedHashMap to preserve the order of the entries as in the JSON file
        Map<String, String> map = new LinkedHashMap<>();

        // Read the JSON from the resource folder
        try (InputStream is = MakeJSONToFlatMap.class.getClassLoader().getResourceAsStream("example_of_json.json")) {
            JsonNode jsonNode = mapper.readTree(is);

            // First call of the method which will traverse the JSON and for each node it will call itself
            getAllKeysUsingJsonNodeFields(jsonNode, "", map);

            map.forEach((k, v) -> System.out.println(k + "  : " + v));
        }
    }

    private static void getAllKeysUsingJsonNodeFields(JsonNode jsonNode, String parentPath, Map<String, String> map) {
        if (jsonNode.isObject()) {
            /**
             * If the jsonNode is Object node then call for every property
             * (nested node) the same method with updated parent path
             */
            Iterator<Map.Entry<String, JsonNode>> fieldIterator = jsonNode.fields();
            while(fieldIterator.hasNext())
            {
                var field = fieldIterator.next();
                getAllKeysUsingJsonNodeFields(field.getValue(), parentPath + "." + field.getKey(), map);
            }
        } else if (jsonNode.isArray()) {
            /**
             * If the jsonNode is Array node then get all inner nodes and
             * call the same method with updated parent path
             */
            ArrayNode arrayField = (ArrayNode) jsonNode;
            for(int index = 0; index < arrayField.size(); index++ )
            {
                getAllKeysUsingJsonNodeFields(arrayField.get(index), parentPath + "[" + index + "]", map);
            }
        } else if (jsonNode.isValueNode()) {
            /**
             * If the jsonNode is isValueNode then populate the map.
             * From the previous calls of the methods the parentPath will
             * have the updated value with the path until the current node
             */
            ValueNode node = (ValueNode) jsonNode;
            String value = node.asText();
            map.put(parentPath, value );
        } else {
            throw new IllegalStateException("Unknown type of node: " + jsonNode);
        }
    }
}

Result:

[0]._id  : 63e744e785730f8b3eb1dda5
[0].index  : 0
[0].isActive  : true
[0].balance  : $3,310.75
[0].age  : 24
[0].name  : Marsh Velasquez
[0].gender  : male
[0].address  : 704 Mill Lane, Dunbar, Iowa, 477
[0].about  : Laboris esse veniam culpa magna sunt consequat culpa elit occaecat non labore id dolore occaecat.
[0].registered  : 2018-04-29T02:17:14 -02:00
[0].latitude  : 23.617941
[0].longitude  : 153.026279
[0].tags[0]  : do
[0].tags[1]  : incididunt
[0].tags[2]  : sint
[0].tags[3]  : qui
[0].tags[4]  : nulla
[0].friends[0].id  : 0
[0].friends[0].name  : Mcintosh Montoya
[0].friends[1].id  : 1
[0].friends[1].name  : Odom Horne
[0].greeting  : Hello, Marsh Velasquez! You have 6 unread messages.
[0].favoriteFruit  : strawberry
[1]._id  : 63e744e73d9ce6418efd7391
[1].index  : 1
[1].isActive  : false
[1].balance  : $3,917.23
[1].age  : 34
[1].name  : Annmarie Gates
[1].gender  : female
[1].address  : 662 Franklin Avenue, Sanford, Virgin Islands, 9048
[1].about  : Deserunt reprehenderit ullamco aute pariatur id. Aute sint amet veniam nisi eiusmod dolor est labore.
[1].registered  : 2014-10-12T03:12:05 -02:00
[1].latitude  : -47.735057
[1].longitude  : -88.535544
[1].tags[0]  : sunt
[1].tags[1]  : elit
[1].tags[2]  : sint
[1].tags[3]  : nostrud
[1].friends[0].id  : 0
[1].friends[0].name  : Sloan Snider
[1].friends[1].id  : 1
[1].friends[1].name  : Elva Rush
[1].friends[2].id  : 2
[1].friends[2].name  : Alana Hyde
[1].greeting  : Hello, Annmarie Gates! You have 3 unread messages.
[1].favoriteFruit  : strawberry

Leave a Comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.