如何在Python中从列表层次结构创建JSON树 [英] How to Create a JSON Tree from a Tabulated Hierarchy in Python

查看:1573
本文介绍了如何在Python中从列表层次结构创建JSON树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我敢肯定,有一种优雅的方法可以用Python(或一键推式Javascript)来做到这一点,但是对于我一生来说,我看不到它.

我有以下格式的CSV文件:

ID, Name, Description
A, A-name,
A100, A100-name, A100-desc
A110, A110-name, A110-desc
A111, A111-name, A111-desc
A112, A112-name, A112-desc
A113, A113-name, A113-desc
A120, A120-name, A120-desc
A131, A131-name, A131-desc
A200, A200-name, A200-desc
B, B-name,
B100, B100-name, B100-desc
B130, B130-name, B130-desc
B131, B131-name, B131-desc
B140, B140-name, B140-desc

,并且我想生成一个分层的JSON结构,以便可以可视化 the JIT .

var json = {  
  "id": "aUniqueIdentifier",  
  "name": "usually a nodes name",  
  "data": {  
    "some key": "some value",  
    "some other key": "some other value"  
   },  
  "children": [ *other nodes or empty* ]  
}; 

我的计划是将ID映射到id,将名称映射到名称,将描述映射到data.desc,并组织层次结构,以便:

  • 根是A和B的父母
  • A是A100和A200的父级
  • A100是A110和A120的父级
  • A110是A111,A112和A113的父级
  • B是B100的父级
  • B100是B130和B140的父级
  • B130是B131的父级

在其他情况下,按ID进行常规排序也存在病理情况,其中A100是A131的父级(预期的A130不存在).

我原本希望找到一个优雅的Python解决方案,但此刻甚至让我望而却步,甚至不理会病态的情况...

解决方案

做到了...

import csv
import json

class Node(dict):
    def __init__(self, (nid, name, ndescr)):
        dict.__init__(self)
        self['id'] = nid
        self['name'] = name.lstrip() # you have badly formed csv....
        self['description'] = ndescr.lstrip()
        self['children'] = []

    def add_node(self, node):
        for child in self['children']:
            if child.is_parent(node):
                child.add_node(node)
                break
        else:
            self['children'].append(node)

    def is_parent(self, node):
        if len(self['id']) == 4 and self['id'][-1] == '0':
            return node['id'].startswith(self['id'][:-1])
        return node['id'].startswith(self['id'])

class RootNode(Node):
    def __init__(self):
        Node.__init__(self, ('Root', '', ''))

    def is_parent(self, node):
        return True

def pretty_print(node, i=0):
    print '%sID=%s NAME=%s %s' % ('\t' * i, node['id'], node['name'], node['description'])
    for child in node['children']:
        pretty_print(child, i + 1)

def main():
    with open('input.csv') as f:
        f.readline() # Skip first line
        root = RootNode()
        for node in map(Node, csv.reader(f)):
            root.add_node(node)

    pretty_print(root)
    print json.dumps(root)

if __name__ == '__main__':
    main()

I'm sure there's an elegant way of doing this in Python (or at a push, Javascript), but for the life of me I can't see it...

I have a CSV file of the form:

ID, Name, Description
A, A-name,
A100, A100-name, A100-desc
A110, A110-name, A110-desc
A111, A111-name, A111-desc
A112, A112-name, A112-desc
A113, A113-name, A113-desc
A120, A120-name, A120-desc
A131, A131-name, A131-desc
A200, A200-name, A200-desc
B, B-name,
B100, B100-name, B100-desc
B130, B130-name, B130-desc
B131, B131-name, B131-desc
B140, B140-name, B140-desc

and I want to generate a hierarchical JSON structure so I can visualise the data in theJIT.

var json = {  
  "id": "aUniqueIdentifier",  
  "name": "usually a nodes name",  
  "data": {  
    "some key": "some value",  
    "some other key": "some other value"  
   },  
  "children": [ *other nodes or empty* ]  
}; 

My plan was to map ID to id, Name to name, Description to data.desc, and organise the hierarchy so that:

  • Root is parent of A and B
  • A is parent of A100 and A200
  • A100 is parent of A110 and A120
  • A110 is parent of A111, A112 and A113
  • B is parent of B100
  • B100 is parent of B130 and B140
  • B130 is parent of B131

There is also a pathological case in the otherwise regular ordering by ID, where A100 is parent of A131 (the expected A130 is not present).

I was hoping to find an elegant Python solution to this, but it's defeating me at the moment, even ignoring the pathological case...

解决方案

This does it...

import csv
import json

class Node(dict):
    def __init__(self, (nid, name, ndescr)):
        dict.__init__(self)
        self['id'] = nid
        self['name'] = name.lstrip() # you have badly formed csv....
        self['description'] = ndescr.lstrip()
        self['children'] = []

    def add_node(self, node):
        for child in self['children']:
            if child.is_parent(node):
                child.add_node(node)
                break
        else:
            self['children'].append(node)

    def is_parent(self, node):
        if len(self['id']) == 4 and self['id'][-1] == '0':
            return node['id'].startswith(self['id'][:-1])
        return node['id'].startswith(self['id'])

class RootNode(Node):
    def __init__(self):
        Node.__init__(self, ('Root', '', ''))

    def is_parent(self, node):
        return True

def pretty_print(node, i=0):
    print '%sID=%s NAME=%s %s' % ('\t' * i, node['id'], node['name'], node['description'])
    for child in node['children']:
        pretty_print(child, i + 1)

def main():
    with open('input.csv') as f:
        f.readline() # Skip first line
        root = RootNode()
        for node in map(Node, csv.reader(f)):
            root.add_node(node)

    pretty_print(root)
    print json.dumps(root)

if __name__ == '__main__':
    main()

这篇关于如何在Python中从列表层次结构创建JSON树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆