Hướng dẫn python traverse json tree - con trăn đi ngang cây json

Hãy nói rằng chúng tôi có tệp JSON sau. Vì lợi ích của ví dụ, nó được mô phỏng bởi một chuỗi. Chuỗi là đầu vào và đối tượng

"ROOT"
    item1
        end1
    item2
        end2
0 phải là đầu ra. Tôi sẽ sử dụng ký hiệu đồ họa của cây để trình bày đầu ra.

Tôi đã tìm thấy các lớp sau để xử lý khái niệm cây trong Python:

class TreeNode(object):
    def __init__(self, data):
        self.data = data
        self.children = []

    def add_child(self, obj):
        self.children.append(obj)

    def __str__(self, level=0):
        ret = "\t"*level+repr(self.data)+"\n"
        for child in self.children:
            ret += child.__str__(level+1)
        return ret

    def __repr__(self):
        return ''

class Tree:
    def __init__(self):
        self.root = TreeNode('ROOT')

    def __str__(self):
        return self.root.__str__()

Tệp đầu vào có thể có độ phức tạp khác nhau:

Trường hợp đơn giản

Input:

"ROOT"
    item1
        end1
    item2
        end2
1

Output:

"ROOT"
    item1
        end1
    item2
        end2

Trường hợp nhúng

Đầu vào:

"ROOT"
    item1
        end1
    item2
        end2
2

Output:

"ROOT"
    item1
        end1
    item2
        item3
            end3

Trường hợp mảng

Input:

"ROOT"
    item1
        end1
    item2
        end2
3

Output:

"ROOT"
    name
        John
    items
        1
            item_name
                lettuce
            price
                2.65
            units
                no
        2   
            item_name
                ketchup
            price
                1.51
            units
                litres

Xin lưu ý rằng mỗi mục trong một mảng được mô tả với một số nguyên (bắt đầu từ 1).

Cho đến nay tôi đã xoay sở để đưa ra chức năng sau đây giải quyết vấn đề cho trường hợp đơn giản. Về mặt trường hợp nhúng, tôi biết rằng tôi phải sử dụng đệ quy nhưng cho đến nay tôi nhận được

"ROOT"
    item1
        end1
    item2
        end2
4.
def create_tree_from_JSON(json, parent=None):
    if not parent:
        tree = Tree()
        node_0 = TreeNode("ROOT")
        tree.root = node_0
        parent = node_0
    else:
        parent = parent

    for key in json:
        if isinstance(json[key], dict):
            head = TreeNode(key)
            create_tree_from_JSON(json[key], head)
        else:
            node = TreeNode(key)
            node.add_child(TreeNode(json[key]))
            parent.add_child(node)

    return tree

Nền tảng của vấn đề

Bạn có thể tự hỏi tại sao tôi cần thay đổi một đối tượng JSON thành cây. Như bạn có thể biết PostgreSQL cung cấp một cách để xử lý các trường JSON trong cơ sở dữ liệu. Đưa ra một đối tượng JSON, tôi có thể nhận được giá trị của bất kỳ trường nào bằng cách sử dụng ký hiệu

"ROOT"
    item1
        end1
    item2
        end2
5 và
"ROOT"
    item1
        end1
    item2
        end2
6. Ở đây và ở đây nhiều hơn về chủ đề. Tôi sẽ tạo các bảng mới dựa trên tên và giá trị của các trường. Thật không may, các đối tượng JSON khác nhau đến mức tôi không thể viết mã
"ROOT"
    item1
        end1
    item2
        end2
7 theo cách thủ công - tôi phải tìm cách tự động thực hiện nó.

Giả sử rằng tôi muốn tạo một bảng dựa trên trường hợp nhúng. Tôi cần nhận mã

"ROOT"
    item1
        end1
    item2
        end2
7 sau:
class TreeNode(object):
    def __init__(self, data):
        self.data = data
        self.children = []

    def add_child(self, obj):
        self.children.append(obj)

    def __str__(self, level=0):
        ret = "\t"*level+repr(self.data)+"\n"
        for child in self.children:
            ret += child.__str__(level+1)
        return ret

    def __repr__(self):
        return ''

class Tree:
    def __init__(self):
        self.root = TreeNode('ROOT')

    def __str__(self):
        return self.root.__str__()
4

Thay thế

"ROOT"
    item1
        end1
    item2
        end2
9 cho
"ROOT"
    item1
        end1
    item2
        item3
            end3
0 và bạn có thể thấy rằng mỗi dòng trong mã SQL chỉ đơn giản là một đường truyền đầu tiên từ "gốc" sang một chiếc lá (chuyển từ nút cuối cùng sang lá luôn được chú thích bằng
"ROOT"
    item1
        end1
    item2
        end2
6).

Chỉnh sửa: Để làm cho câu hỏi rõ ràng hơn, tôi sẽ thêm truy vấn

"ROOT"
    item1
        end1
    item2
        end2
7 mục tiêu cho trường hợp mảng. Tôi muốn có nhiều truy vấn như có các yếu tố trong mảng:
class TreeNode(object):
    def __init__(self, data):
        self.data = data
        self.children = []

    def add_child(self, obj):
        self.children.append(obj)

    def __str__(self, level=0):
        ret = "\t"*level+repr(self.data)+"\n"
        for child in self.children:
            ret += child.__str__(level+1)
        return ret

    def __repr__(self):
        return ''

class Tree:
    def __init__(self):
        self.root = TreeNode('ROOT')

    def __str__(self):
        return self.root.__str__()
9

Giải pháp cho đến nay (07.05.2019)

Tôi đang thử nghiệm giải pháp hiện tại cho thời điểm này:

"ROOT"
    item1
        end1
    item2
        end2
0

Tôi hiện đang làm việc trên một JSON như thế này:

"ROOT"
    item1
        end1
    item2
        end2
1

Trong đầu ra, tôi nhận được phần tử hằng số duy nhất là thứ tự các dòng được xử lý bằng logic mảng. Thứ tự của các dòng khác khác nhau. Đầu ra tôi muốn nhận là một thứ có tính đến thứ tự của các khóa:

"ROOT"
    item1
        end1
    item2
        end2
2