Как создать дерево JSON из табличной иерархии в Python
Я уверен, что есть элегантный способ сделать это в 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, чтобы я мог визуализировать данные в 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 и организовать иерархию так, чтобы:
- Root является родителем A и B
- A является родителем A100 и A200
- A100 является родителем A110 и A120
- A110 является родителем A111, A112 и A113
- B является родителем B100
- B100 является родителем B130 и B140
- B130 является родителем B131
Существует также патологический случай при регулярном упорядочении по идентификатору, где A100 является родителем A131 (ожидаемый A130 отсутствует).
Я надеялся найти элегантное решение Python для этого, но в настоящий момент он побеждает меня, даже игнорируя патологический случай...
1 ответ
Решение
Это делает это...
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()