How would I group JSON objects by id’s to make a nested JSON in Python? The JSON is structured this way:
[{ "id": "4", "title": "Part 4", "children": {} },{ "id": "4.1.", "title": "Section 4.1. Transition Rule", "children": {} }, { "id": "4.1.1.", "title": "4.1.1. Transition, January 2014", "children": {} }, { "id": "4.1.1.1.", "title": "4.1.1.1. Transition Rule", "children": {} }, { "id": "4.1.2.", "title": "4.1.2. Transition, January 2015", "children": {} }, { "id": "4.1.2.1.", "title": "4.1.2.1. Transition Rule", "children": {} }, ]]
The goal is to have a tree structure where each object(section) contains all its subsections going from 4 to 4.1 > 4.1.1 > 4.1.1.1.
The snippet of the required output is below:
[ { "id":"4", "title":"Part 4", "children":{ { "id":"4.1.", "title":"Section 4.1. Transition Rule", "children":{ { "id":"4.1.1.", "title":"4.1.1. Transition, January 2014", "children":{ { "id":"4.1.1.1.", "title":"4.1.1.1. Transition Rule", "children":{ } } } }, { "id":"4.1.2.", "title":"4.1.2. Transition, January 2015", "children":{ { "id":"4.1.2.1.", "title":"4.1.2.1. Transition Rule", "children":{
Advertisement
Answer
You can use recursion:
from collections import defaultdict def get_tree(d): _d, r = defaultdict(list), [] for i in d: _d[i['key'][0]].append({**i, 'key':i['key'][1:]}) for b in _d.values(): j, k = [l for l in b if not l['key']], [l for l in b if l['key']] if j: r.extend([{**{x:y for x, y in i.items() if x != 'key'}, 'children':get_tree(k)} for i in j]) else: r.extend(get_tree(k)) return r data = [{'id': '4', 'title': 'Part 4', 'children': {}}, {'id': '4.1.', 'title': 'Section 4.1. Transition Rule', 'children': {}}, {'id': '4.1.1.', 'title': '4.1.1. Transition, January 2014', 'children': {}}, {'id': '4.1.1.1.', 'title': '4.1.1.1. Transition Rule', 'children': {}}, {'id': '4.1.2.', 'title': '4.1.2. Transition, January 2015', 'children': {}}, {'id': '4.1.2.1.', 'title': '4.1.2.1. Transition Rule', 'children': {}}, {'id': '4.1.3.', 'title': '4.1.3. Transition, January 2017', 'children': {}}]
import json print(json.dumps(get_tree([{**i, 'key':[*filter(None, i['id'].split('.'))]} for i in data]), indent=4))
Output:
[ { "id": "4", "title": "Part 4", "children": [ { "id": "4.1.", "title": "Section 4.1. Transition Rule", "children": [ { "id": "4.1.1.", "title": "4.1.1. Transition, January 2014", "children": [ { "id": "4.1.1.1.", "title": "4.1.1.1. Transition Rule", "children": [] } ] }, { "id": "4.1.2.", "title": "4.1.2. Transition, January 2015", "children": [ { "id": "4.1.2.1.", "title": "4.1.2.1. Transition Rule", "children": [] } ] }, { "id": "4.1.3.", "title": "4.1.3. Transition, January 2017", "children": [] } ] } ] } ]