将常规json文件转换为d3 flare.json使用的父子分层json

时间:2018-10-29 16:41:09

标签: javascript json typescript

我有一个具有以下结构的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"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }

我希望有一个父子层次关系,以便更容易绘制带有节点的可折叠树图。如果缩进不合适,请原谅。

2 个答案:

答案 0 :(得分:2)

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

要使用import { Directive, HostListener, ElementRef, Renderer2, OnInit } from '@angular/core'; @Directive({ selector: '[appDropdown]' }) export class AppDropdownDirective implements OnInit { private isShow = false; private classShow = 'show'; private parentNode: HTMLElement; private siblingNode: HTMLElement; constructor(private elementRef: ElementRef, private renderer: Renderer2) {} ngOnInit() { this.parentNode = this.renderer.parentNode(this.elementRef.nativeElement); this.siblingNode = this.renderer.nextSibling(this.elementRef.nativeElement); } @HostListener('click') open() { this.isShow = !this.isShow; if (this.isShow) { this.addClass(); } else { this.removeClass(); } } @HostListener('document:click', ['$event']) clickout(event) { if (this.elementRef.nativeElement !== event.target && this.isShow) { this.removeClass(); this.isShow = false; } } private addClass() { this.renderer.addClass(this.parentNode, this.classShow); this.renderer.addClass(this.siblingNode, this.classShow); } private removeClass() { this.renderer.removeClass(this.parentNode, this.classShow); this.renderer.removeClass(this.siblingNode, this.classShow); } } 元素获取所需样式,您需要移交一个新对象,该对象遵循与给定数据的内部对象相同的构建规则。

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);

答案 1 :(得分:1)

这是一种可能性:

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节点,因为根据注释,这些节点不是必需的。

更新

尼娜·舒尔茨(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))