在java中展平三层嵌套的JSON字符串

要求是为输入 JSON 对象创建一个通用的扁平化实用程序以扁平化 JSON 对象。


示例 JSON 如下所示


{

  "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

  }

}

我一直在尝试将其扁平化为 3 个级别,并提出了以下实用程序。但是,当我必须处理数组和 String、long、Timestamp 等类型的值时,事情变得复杂。此外,我无法理解如何维护嵌套键的唯一性。


任何帮助是极大的赞赏。


Cats萌萌
浏览 146回答 4
4回答

交互式爱情

您可以查看json-flattener。

慕哥9229398

为了避免与键名称冲突,您可以使用JSON 指针规范来创建它们。它也受到Jackson库的支持,因此您可以稍后使用它们来遍历JsonNode节点。简单的实现如下所示: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);    }  }}上面的代码打印: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 => 14789654Use 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

阿波罗的战车

试试这个代码:public static void flattenJson(JsonNode node, String parent, Map<String, ValueNode> map) {&nbsp; &nbsp; if (node instanceof ValueNode) {&nbsp; &nbsp; &nbsp; &nbsp; map.put(parent, (ValueNode)node);&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; String prefix = parent == null ? "" : parent + ".";&nbsp; &nbsp; &nbsp; &nbsp; if (node instanceof ArrayNode) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ArrayNode arrayNode = (ArrayNode)node;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for(int i = 0; i < arrayNode.size(); i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flattenJson(arrayNode.get(i), prefix + i, map);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; } else if (node instanceof ObjectNode) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ObjectNode objectNode = (ObjectNode) node;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (Iterator<Map.Entry<String, JsonNode>> it = objectNode.fields(); it.hasNext(); ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Map.Entry<String, JsonNode> field = it.next();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flattenJson(field.getValue(), prefix + field.getKey(), map);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new RuntimeException("unknown json node");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}public static Map<String, ValueNode> flattenJson(JsonNode input) {&nbsp; &nbsp; Map<String, ValueNode> map = new LinkedHashMap<>();&nbsp; &nbsp; flattenJson(input, null, map);&nbsp; &nbsp; return map;}然后你可以打电话&nbsp; &nbsp; ObjectMapper om = new ObjectMapper();&nbsp; &nbsp; JsonNode jsonNode = om.readTree(json);&nbsp; &nbsp; Map<String, ValueNode> m = flattenJson(jsonNode);&nbsp; &nbsp; for (Map.Entry<String, ValueNode> kv : m.entrySet()) {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(kv.getKey() + "=" + kv.getValue().asText());&nbsp; &nbsp; }输出:Source=source-1Rows.0.Keys.device-id=BC04-EBH-N3K-01Rows.0.Keys.interface-name=TenGigE0/0/0/39Rows.0.Keys.node-name=0/0/CPU0Rows.0.Timestamp=1567621527656Rows.0.inner.donm.id=0062Rows.0.inner.donm.mol.rem=30Rows.0.inner.donm.mol.len=11Rows.0.inner.donm.mol.org.ldp.0.t=486Rows.0.inner.donm.mol.org.ldp.0.o=322Rows.0.inner.donm.mol.org.ldp.1.t=487Rows.0.inner.donm.mol.org.ldp.1.o=32Rows.0.inner.donm.mol.org.ldp.1.twss=1Rows.0.inner.donm.mol.org.ldp.1.tlv=00:01Rows.0.inner.donm.mol.chlen=14Rows.0.inner.donm.mol.poe=5Rows.0.inner.donm.mol.combs=10Rows.0.inner.donm.mol.chaype=4Rows.0.inner.donm.mol.rek=0Rows.0.inner.donm.mol.rem-um=67Rows.0.inner.donm.detail.enas=B,RRows.0.inner.donm.detail.systes=B,RRows.0.inner.donm.detail.timng=91Rows.0.inner.donm.detail.syn=CRows.0.inner.donm.detail.met-type=0Rows.0.inner.donm.detail.neses.lldEDIT.0.ium=830Rows.0.inner.donm.detail.neses.lldEDIT.0.m=1Rows.0.inner.donm.detail.neses.lldEDIT.0.ass.ape=ipv4Rows.0.inner.donm.detail.neses.lldEDIT.0.ass.ipvs=94Rows.0.inner.donm.detail.pess=0008Rows.0.inner.donm.detail.por]d=0Rows.0.inner.donm.detail.pon=BCtiveRows.0.inner.donm.detail.sysme=BC1Rows.0.inner.donm.reme=Bu1Rows.0.inner.donm.hean=0Rows.0.inner.donm.porl=Et1Tey.epath=CgetailTey.sustr=MXTey.coime=1567621527653Tey.msp=1567621527653Tey.come=1567621527660Tey.nor=BC5Tey.cid=14789654

墨色风雨

只需将每个级别的键附加到更高级别的键中即可创建键的命名空间。换句话说,你的扁平 JSON 的键将是:{&nbsp;"L1key::L2key": "L2val",&nbsp;"L1key": "L1val",&nbsp;"L1key::L2key::L3key": "L3val"}这样你就可以保证唯一性,而且你也可以从中创建原始的 json。最后确保级别分隔符(此处::)不会出现在您的密钥中。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java