Flattening a 3 level nested JSON string in java

flatten json to nested json
how to map nested json object in java
java flatten nested object
convert nested json to java object using jackson
convert nested json to flat json c#
spring boot nested json example
convert nested json to hashmap java
excel to nested json java

The requirement is to create a generic flattening utility for an input JSON object to a flattened JSON object.

The sample JSON looks like the below

{
  "Source": "source-1",
  "Rows": [
    {
      "Keys": {
        "device-id": "BC04-EBH-N3K-01",
        "interface-name": "TenGigE0/0/0/39",
        "node-name": "0/0/CPU0"
      },
      "Timestamp": 1567621527656,
      "inner": {
        "donm": {
          "id": "0062",
          "mol": {
            "rem": 30,
            "len": 11,
            "org": {
              "ldp": [
                {
                  "t": 486,
                  "o": 322
                },
                {
                  "t": 487,
                  "o": 32,
                  "twss": 1,
                  "tlv": "00:01"
                }
              ]
            },
            "chlen": 14,
            "poe": 5,
            "combs": 10,
            "chaype": 4,
            "rek": 0,
            "rem-um": 67
          },
          "detail": {
            "enas": "B,R",
            "systes": "B,R",
            "timng": 91,
            "syn": "C",
            "met-type": 0,
            "neses": {
              "lldEDIT": [
                {
                  "ium": 830,
                  "m": 1,
                  "ass": {
                    "ape": "ipv4",
                    "ipvs": "94"
                  }
                }
              ]
            },
            "pess": "0008",
            "por]d": 0,
            "pon": "BCtive",
            "sysme": "BC1"
          },
          "reme": "Bu1",
          "hean": 0,
          "porl": "Et1"
        }
      }
    }

  ],
  "Tey": {
    "epath": "Cgetail",
    "sustr": "MX",
    "coime": 1567621527653,
    "msp": 1567621527653,
    "come": 1567621527660,
    "nor": "BC5",
    "cid": 14789654
  }
}

I have been trying to flatten it to 3 levels and came up with the below utility. But, The things are getting complicated when I have to deal with Arrays and values of type String, long, Timestamp, etc. Also, I am unable to understand how the nested keys can be maintained for uniqueness.

public static Map<String,Object> flattenJson(JsonNode input){
        Map<String,Object> finalMap = new HashMap<>();

        ObjectMapper datamapper = new ObjectMapper();
        Map<String,Object> topLevelJsonMap = datamapper.convertValue(input,Map.class);
        Set<String> topLevelKeys = topLevelJsonMap.keySet();

        for(String topLevelKey : topLevelKeys){

            System.out.println("Key :::: "+topLevelKey);

            Object topLevelData = topLevelJsonMap.get(topLevelKey);
            System.out.println("value :::: "+topLevelData.toString());

            if(topLevelData instanceof ArrayNode){
                ArrayNode arrayOfData = (ArrayNode) topLevelData;
                for(JsonNode dataNode : arrayOfData){
                    flattenJson(input);
                }
            } else if(topLevelData instanceof JsonNode){
                Map<String,Object> innerLevelJsonMap = datamapper.convertValue(topLevelData,Map.class);
                Set<String> innerLevelKeys = innerLevelJsonMap.keySet();
                for(String innerLevelKey : innerLevelKeys){
                    System.out.println("inner key :::: "+innerLevelKey);
                    flattenJson((JsonNode) innerLevelJsonMap.get(innerLevelKey));
                }
            }else {
               finalMap.put(topLevelKey,topLevelData);
            }
        }
        return finalMap;
    }

Any help is greatly appreciated.

To avoid conflicts with key names you can use JSON Pointer specification to create them. It is also supported by Jackson library, so you can use them later to traverse the JsonNode node.

Simple implementation could look like below:

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.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

public class JsonApp {

  public static void main(String[] args) throws Exception {
    File jsonFile = new File("./test.json");

    ObjectMapper mapper = new ObjectMapper();
    JsonNode root = mapper.readTree(jsonFile);
    Map<String, JsonNode> map = new JsonFlattener(root).flatten();

    System.out.println("Use key-value pairs:");
    map.forEach(
        (k, v) -> {
          System.out.println(k + " => " + v);
        });

    System.out.println();
    System.out.println("Use pointers:");
    map.forEach(
        (k, v) -> {
          System.out.println(k + " => " + root.at(k));
        });
  }
}

class JsonFlattener {

  private final Map<String, JsonNode> json = new LinkedHashMap<>(64);
  private final JsonNode root;

  JsonFlattener(JsonNode node) {
    this.root = Objects.requireNonNull(node);
  }

  public Map<String, JsonNode> flatten() {
    process(root, "");
    return json;
  }

  private void process(JsonNode node, String prefix) {
    if (node.isObject()) {
      ObjectNode object = (ObjectNode) node;
      object
          .fields()
          .forEachRemaining(
              entry -> {
                  process(entry.getValue(), prefix + "/" + entry.getKey());
              });
    } else if (node.isArray()) {
      ArrayNode array = (ArrayNode) node;
      AtomicInteger counter = new AtomicInteger();
      array
          .elements()
          .forEachRemaining(
              item -> {
                process(item, prefix + "/" + counter.getAndIncrement());
              });
    } else {
      json.put(prefix, node);
    }
  }
}

Above code prints:

Use key-value pairs:
/Source => "source-1"
/Rows/0/Keys/device-id => "BC04-EBH-N3K-01"
/Rows/0/Keys/interface-name => "TenGigE0/0/0/39"
/Rows/0/Keys/node-name => "0/0/CPU0"
/Rows/0/Timestamp => 1567621527656
/Rows/0/inner/donm/id => "0062"
/Rows/0/inner/donm/mol/rem => 30
/Rows/0/inner/donm/mol/len => 11
/Rows/0/inner/donm/mol/org/ldp/0/t => 486
/Rows/0/inner/donm/mol/org/ldp/0/o => 322
/Rows/0/inner/donm/mol/org/ldp/1/t => 487
/Rows/0/inner/donm/mol/org/ldp/1/o => 32
/Rows/0/inner/donm/mol/org/ldp/1/twss => 1
/Rows/0/inner/donm/mol/org/ldp/1/tlv => "00:01"
/Rows/0/inner/donm/mol/chlen => 14
/Rows/0/inner/donm/mol/poe => 5
/Rows/0/inner/donm/mol/combs => 10
/Rows/0/inner/donm/mol/chaype => 4
/Rows/0/inner/donm/mol/rek => 0
/Rows/0/inner/donm/mol/rem-um => 67
/Rows/0/inner/donm/detail/enas => "B,R"
/Rows/0/inner/donm/detail/systes => "B,R"
/Rows/0/inner/donm/detail/timng => 91
/Rows/0/inner/donm/detail/syn => "C"
/Rows/0/inner/donm/detail/met-type => 0
/Rows/0/inner/donm/detail/neses/lldEDIT/0/ium => 830
/Rows/0/inner/donm/detail/neses/lldEDIT/0/m => 1
/Rows/0/inner/donm/detail/neses/lldEDIT/0/ass/ape => "ipv4"
/Rows/0/inner/donm/detail/neses/lldEDIT/0/ass/ipvs => "94"
/Rows/0/inner/donm/detail/pess => "0008"
/Rows/0/inner/donm/detail/por]d => 0
/Rows/0/inner/donm/detail/pon => "BCtive"
/Rows/0/inner/donm/detail/sysme => "BC1"
/Rows/0/inner/donm/reme => "Bu1"
/Rows/0/inner/donm/hean => 0
/Rows/0/inner/donm/porl => "Et1"
/Tey/epath => "Cgetail"
/Tey/sustr => "MX"
/Tey/coime => 1567621527653
/Tey/msp => 1567621527653
/Tey/come => 1567621527660
/Tey/nor => "BC5"
/Tey/cid => 14789654

Use pointers:
/Source => "source-1"
/Rows/0/Keys/device-id => "BC04-EBH-N3K-01"
/Rows/0/Keys/interface-name => "TenGigE0/0/0/39"
/Rows/0/Keys/node-name => "0/0/CPU0"
/Rows/0/Timestamp => 1567621527656
/Rows/0/inner/donm/id => "0062"
/Rows/0/inner/donm/mol/rem => 30
/Rows/0/inner/donm/mol/len => 11
/Rows/0/inner/donm/mol/org/ldp/0/t => 486
/Rows/0/inner/donm/mol/org/ldp/0/o => 322
/Rows/0/inner/donm/mol/org/ldp/1/t => 487
/Rows/0/inner/donm/mol/org/ldp/1/o => 32
/Rows/0/inner/donm/mol/org/ldp/1/twss => 1
/Rows/0/inner/donm/mol/org/ldp/1/tlv => "00:01"
/Rows/0/inner/donm/mol/chlen => 14
/Rows/0/inner/donm/mol/poe => 5
/Rows/0/inner/donm/mol/combs => 10
/Rows/0/inner/donm/mol/chaype => 4
/Rows/0/inner/donm/mol/rek => 0
/Rows/0/inner/donm/mol/rem-um => 67
/Rows/0/inner/donm/detail/enas => "B,R"
/Rows/0/inner/donm/detail/systes => "B,R"
/Rows/0/inner/donm/detail/timng => 91
/Rows/0/inner/donm/detail/syn => "C"
/Rows/0/inner/donm/detail/met-type => 0
/Rows/0/inner/donm/detail/neses/lldEDIT/0/ium => 830
/Rows/0/inner/donm/detail/neses/lldEDIT/0/m => 1
/Rows/0/inner/donm/detail/neses/lldEDIT/0/ass/ape => "ipv4"
/Rows/0/inner/donm/detail/neses/lldEDIT/0/ass/ipvs => "94"
/Rows/0/inner/donm/detail/pess => "0008"
/Rows/0/inner/donm/detail/por]d => 0
/Rows/0/inner/donm/detail/pon => "BCtive"
/Rows/0/inner/donm/detail/sysme => "BC1"
/Rows/0/inner/donm/reme => "Bu1"
/Rows/0/inner/donm/hean => 0
/Rows/0/inner/donm/porl => "Et1"
/Tey/epath => "Cgetail"
/Tey/sustr => "MX"
/Tey/coime => 1567621527653
/Tey/msp => 1567621527653
/Tey/come => 1567621527660
/Tey/nor => "BC5"
/Tey/cid => 14789654

How to Flatten or Unflatten Complex JSON objects into Flat & Map , How to deserialize nested JSON into flat, Map-like structure? Step-3. Copy java code to your Eclipse: JsonFlattener: A Java utility used to FLATTEN nested JSON objects Map<String, Object> flattenedJsonMap = JsonFlattener. Better Logging Tips & Create Your Own Logging Level using Log4j  A simple forEach or flatMap methods in Java 8, in combination with method references, can be used for flattening nested collections. You can find the code discussed in this article over on GitHub . Java bottom

Try this code:

public static void flattenJson(JsonNode node, String parent, Map<String, ValueNode> map) {
    if (node instanceof ValueNode) {
        map.put(parent, (ValueNode)node);
    } else {
        String prefix = parent == null ? "" : parent + ".";
        if (node instanceof ArrayNode) {
            ArrayNode arrayNode = (ArrayNode)node;
            for(int i = 0; i < arrayNode.size(); i++) {
                flattenJson(arrayNode.get(i), prefix + i, map);
            }
        } else if (node instanceof ObjectNode) {
            ObjectNode objectNode = (ObjectNode) node;
            for (Iterator<Map.Entry<String, JsonNode>> it = objectNode.fields(); it.hasNext(); ) {
                Map.Entry<String, JsonNode> field = it.next();
                flattenJson(field.getValue(), prefix + field.getKey(), map);
            }
        } else {
            throw new RuntimeException("unknown json node");
        }
    }
}

public static Map<String, ValueNode> flattenJson(JsonNode input) {
    Map<String, ValueNode> map = new LinkedHashMap<>();
    flattenJson(input, null, map);
    return map;
}

Then you can call

    ObjectMapper om = new ObjectMapper();
    JsonNode jsonNode = om.readTree(json);
    Map<String, ValueNode> m = flattenJson(jsonNode);
    for (Map.Entry<String, ValueNode> kv : m.entrySet()) {
        System.out.println(kv.getKey() + "=" + kv.getValue().asText());
    }

Output:

Source=source-1
Rows.0.Keys.device-id=BC04-EBH-N3K-01
Rows.0.Keys.interface-name=TenGigE0/0/0/39
Rows.0.Keys.node-name=0/0/CPU0
Rows.0.Timestamp=1567621527656
Rows.0.inner.donm.id=0062
Rows.0.inner.donm.mol.rem=30
Rows.0.inner.donm.mol.len=11
Rows.0.inner.donm.mol.org.ldp.0.t=486
Rows.0.inner.donm.mol.org.ldp.0.o=322
Rows.0.inner.donm.mol.org.ldp.1.t=487
Rows.0.inner.donm.mol.org.ldp.1.o=32
Rows.0.inner.donm.mol.org.ldp.1.twss=1
Rows.0.inner.donm.mol.org.ldp.1.tlv=00:01
Rows.0.inner.donm.mol.chlen=14
Rows.0.inner.donm.mol.poe=5
Rows.0.inner.donm.mol.combs=10
Rows.0.inner.donm.mol.chaype=4
Rows.0.inner.donm.mol.rek=0
Rows.0.inner.donm.mol.rem-um=67
Rows.0.inner.donm.detail.enas=B,R
Rows.0.inner.donm.detail.systes=B,R
Rows.0.inner.donm.detail.timng=91
Rows.0.inner.donm.detail.syn=C
Rows.0.inner.donm.detail.met-type=0
Rows.0.inner.donm.detail.neses.lldEDIT.0.ium=830
Rows.0.inner.donm.detail.neses.lldEDIT.0.m=1
Rows.0.inner.donm.detail.neses.lldEDIT.0.ass.ape=ipv4
Rows.0.inner.donm.detail.neses.lldEDIT.0.ass.ipvs=94
Rows.0.inner.donm.detail.pess=0008
Rows.0.inner.donm.detail.por]d=0
Rows.0.inner.donm.detail.pon=BCtive
Rows.0.inner.donm.detail.sysme=BC1
Rows.0.inner.donm.reme=Bu1
Rows.0.inner.donm.hean=0
Rows.0.inner.donm.porl=Et1
Tey.epath=Cgetail
Tey.sustr=MX
Tey.coime=1567621527653
Tey.msp=1567621527653
Tey.come=1567621527660
Tey.nor=BC5
Tey.cid=14789654

Mapping Nested Values with Jackson, Learn three ways to deserialize nested JSON values in Java using the to map nested values with Jackson to flatten out a complex data structure. While the structure is contrived, note that we include properties that are nested two levels deep: ? 3. 4. 5. 6. 7. 8. 9. public class Product {. private String id;. A Java utility used to FLATTEN nested JSON objects and even more to UNFLATTEN it back - wnameless/json-flattener

Just create namespace of the keys by appending each level key into the key from higher level. In other words your flattened JSON's keys would be:

{
 "L1key::L2key": "L2val",
 "L1key": "L1val",
 "L1key::L2key::L3key": "L3val"
}

This way you guarantee uniqueness but also you can create the original json from this as well. Lastly be sure that the level separator (here ::) will not be present in your key.

HTH

How to Flatten Deeply Nested JSON Objects in Non-Recursive , Unit test with another example “pets2” which is 3-level nested at key “dolphin”. A list [{“bird”:”bluejay”},{“fish”:”dolphin”}] is packed as the value of  How to deserialize nested JSON into flat, Map-like structure? Couple of days back I got a questions on how to flatten JSON Object which may be simple of Complex in structure? JsonFlattener is a very powerful maven utility exactly for the same. Let’s take a look at example. You need to import below Maven Dependency to your project.

JavaScript: flattening a JSON – techtutorialsx, In this tutorial we will learn how to flatten a nested JSON object using the flat library. When flattening an object, we will obtain a new object with one level deep, In this case, each element of the array will be mapped to a different 3. 4. 5. 6. 7. 8. 9. 10. const obj = {. name: "John" ,. age: 10,. address: {. The code recursively extracts values out of the object into a flattened dictionary. json_normalize can be applied to the output of flatten_object to produce a python dataframe: flat = flatten_json(sample_object2) json_normalize(flat)

Flattening Nested JSON, The simplest input we could be given is a JSON object that's either empty or only one-level deep. In that case we just return the input as the output  In this tutorial, we demonstrated several ways of using Jackson to parse JSON containing nested values. Have a look at our main Jackson Tutorial page for more examples. And, as always, code snippets, can be found over on GitHub .

JSON Flatten Spec, Defining the JSON Flatten Spec allows nested JSON fields to be flattened during expr, String, Defines an expression for accessing the field within the JSON For convenience, when defining a root-level field, it is possible to define only the [{"invalid": "true"}] and [1,2,3] are not. http://jsonpath.herokuapp.com/ is useful for  How to parse nested JSON object in Java. By Atul Rai | March 31, 2017 | Updated: July 20, 2019 In this Java tutorial, we are going to parse or read the nested JSON object using the library JSON.simple. To parse the Nested Object, we need to create the object of parent object first.