【问题标题】:Converting a regular json file to a parent-child hierarchical json as used by d3 flare.json将常规 json 文件转换为 d3flare.json 使用的父子分层 json
【发布时间】:2019-04-02 15:46:39
【问题描述】:

我有一个结构如下的 json 文件:

  {
    "a": "b",
    "c": "d",
    "e": {
      "f": "g",
      "h": "i"
    }
  }

我希望它具有以下结构:

  {
    "name": "Root",
    "parent": "null",
    "children": [
      {
        "name": "a",
        "parent": "Root",
        "children": [
          {
            "name": "b",
            "parent": "a"
          }
        ]
      },
      {
        "name": "c",
        "parent": "Root",
        "children": [
          {
            "name": "d",
            "parent": "d"
          }
        ]
      },
      {
        "name": "e",
        "parent": "Root",
        "children": [
          {
            "name": "f",
            "parent": "e",
            "children": [
              {
                "name": "g",
                "parent": "f"
              },
              {
                "name": "h",
                "parent": "e",
                "children": [
                  {
                    "name": "i",
                    "parent": "h"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }

我想有一个父子层次关系,这样可以更容易地绘制一个带有节点的可折叠树图。如果缩进不正确,请原谅。

【问题讨论】:

  • 欢迎来到 StackOverflow!请访问Help Center,使用tour 并在此处阅读asking good questions
  • 为什么是parent 节点?他们不会添加结构中尚未包含的任何信息。
  • 你试过什么?您必须遍历键并创建自己的结果 json,可能使用某种递归。
  • 为什么会有一个外部数据数组?
  • 循环您的数据并构建新对象,实际上没有任何自动魔术方法可以做到这一点,但正如其他人指出的那样,请考虑在编码之前重新设计您的数据模型。

标签: javascript json typescript


【解决方案1】:

您可以通过使用对象和父值来使用递归方法。

要使用Root 元素获得想要的样式,您需要交出一个新对象,该对象遵循与给定数据的内部对象相同的构建规则。

{
    Root: data[0]
}

const
    getObjects = (o, parent) =>
        o && typeof o === 'object'
            ? Object.entries(o).map(([name, v]) => ({ name, parent, children: getObjects(v, name) }))
            : [{ name: o, parent }];

var data = [{ a: "b", c: "d", e: { f: "g", h: "i" } }],
    result = getObjects({ Root: data[0] }, 'null');

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    这是一种可能性:

    const treeify = (orig) => Object.entries(orig).map(
      ([k, v]) => (Object.assign({name: k}, typeof v == 'object'
        ? {children: treeify(v)} 
        : {children: {name: v}}
      ))
    )
    const convert = (orig) => ({name: 'Root', children: treeify(orig)})
    
    const orig = {"a": "b", "c": "d", "e": {"f": "g", "h": "i"}}
    
    console.log(convert(orig))

    treeify 处理繁重的工作,convert 是一个简单的包装器,它添加了Root 节点。请注意,没有尝试创建 parent 节点,因为根据 cmets,这些节点不是必需的。

    更新

    Nina Scholz 的答案很明确,它确实提供了父母(我认为这会更困难!)建议这个版本的替代方案也包括它。即使没有父母,我更喜欢这个版本的convert

    const treeify = (orig, parent) => Object.entries(orig).map(
      ([k, v]) => (Object.assign({name: k, parent}, typeof v == 'object' 
        ? {children: treeify(v, k)} 
        : {children: {name: v, parent: k}}
      ))
    )
    
    const convert = (orig) => treeify({Root: orig}, 'null')[0]
    
    const orig = {"a": "b", "c": "d", "e": {"f": "g", "h": "i"}}
    console.log(convert(orig))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-04
      相关资源
      最近更新 更多