关键词

python递归查询菜单并转换成json实例

对于这个问题,我们来逐步分析。

一、递归查询菜单

假设我们有如下的菜单数据:

[
    {"id": 1, "name": "菜单1", "parent_id": None},
    {"id": 2, "name": "菜单2", "parent_id": None},
    {"id": 3, "name": "菜单3", "parent_id": 1},
    {"id": 4, "name": "菜单4", "parent_id": 1},
    {"id": 5, "name": "菜单5", "parent_id": 2},
    {"id": 6, "name": "菜单6", "parent_id": 4},
    {"id": 7, "name": "菜单7", "parent_id": 6},
    {"id": 8, "name": "菜单8", "parent_id": 5}
]

通过递归查询菜单,我们希望得到以下结果:

菜单1
├── 菜单3
└── 菜单4
    └── 菜单6
        └── 菜单7
菜单2
└── 菜单5
    └── 菜单8

我们可以使用如下的 Python 代码来实现递归查询菜单:

def get_menu_children(menu, parent_id=None):
    children = []
    for item in menu:
        if item['parent_id'] == parent_id:
            item_children = get_menu_children(menu, item['id'])
            if item_children:
                item['children'] = item_children
            children.append(item)
    return children

在上述代码中,我们通过遍历菜单,将所有 parent_id 为指定值的项目作为当前 item 的子菜单添加进去。由于可能存在多层子菜单,因此对所有子菜单也递归调用这个函数,直到找到所有子菜单。

示例代码:

menu_data = [
    {"id": 1, "name": "菜单1", "parent_id": None},
    {"id": 2, "name": "菜单2", "parent_id": None},
    {"id": 3, "name": "菜单3", "parent_id": 1},
    {"id": 4, "name": "菜单4", "parent_id": 1},
    {"id": 5, "name": "菜单5", "parent_id": 2},
    {"id": 6, "name": "菜单6", "parent_id": 4},
    {"id": 7, "name": "菜单7", "parent_id": 6},
    {"id": 8, "name": "菜单8", "parent_id": 5}
]

menu_tree = get_menu_children(menu_data)
for item in menu_tree:
    print(item['name'])
    if 'children' in item:
        for child in item['children']:
            print("  ├──", child['name'])
            if 'children' in child:
                for sub_child in child['children']:
                    print("  │   └──", sub_child['name'])

二、转换成Json实例

接下来,我们把上述菜单数据转换成 Json 实例。转换过程如下:

def menu_to_json(menu):
    res = []
    for item in menu:
        res.append({
            "id": item['id'],
            "name": item['name'],
        })
        if 'children' in item:
            res[-1]['children'] = menu_to_json(item['children'])
    return res

在上述代码中,我们通过遍历菜单,把每个 item 转化为 Json 语法,包含 idname,并根据是否含有子菜单来判断是否要添加 children 项。

这样,我们就得到了如下的 Json 实例:

[
    {
        "id":1,
        "name":"菜单1",
        "children":[
            {
                "id":3,
                "name":"菜单3"
            },
            {
                "id":4,
                "name":"菜单4",
                "children":[
                    {
                        "id":6,
                        "name":"菜单6",
                        "children":[
                            {
                                "id":7,
                                "name":"菜单7"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "id":2,
        "name":"菜单2",
        "children":[
            {
                "id":5,
                "name":"菜单5",
                "children":[
                    {
                        "id":8,
                        "name":"菜单8"
                    }
                ]
            }
        ]
    }
]

另外,我们可以把 Python 字典转换成 Json,如下所示:

import json

menu_dict = menu_to_json(menu_data)
menu_json = json.dumps(menu_dict, ensure_ascii=False, indent=4)
print(menu_json)

输出结果:

[
    {
        "id": 1,
        "name": "菜单1",
        "children": [
            {
                "id": 3,
                "name": "菜单3"
            },
            {
                "id": 4,
                "name": "菜单4",
                "children": [
                    {
                        "id": 6,
                        "name": "菜单6",
                        "children": [
                            {
                                "id": 7,
                                "name": "菜单7"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "id": 2,
        "name": "菜单2",
        "children": [
            {
                "id": 5,
                "name": "菜单5",
                "children": [
                    {
                        "id": 8,
                        "name": "菜单8"
                    }
                ]
            }
        ]
    }
]

三、示例说明

以上就是 Python 递归查询菜单并转换成 Json 实例的代码实现过程。下面提供两个示例。

示例1

假设我们需要从一个有多层嵌套的分类树中取出一条分类链上的所有分类节点及其所有的子节点,并按照节点在分类层级链中的顺序,转换成 Json,如下所示:

category_data = [
    {"id": 1, "name": "电器", "parent_id": None},
    {"id": 2, "name": "手机", "parent_id": 1},
    {"id": 3, "name": "笔记本电脑", "parent_id": 1},
    {"id": 4, "name": "智能电视", "parent_id": 1},
    {"id": 5, "name": "苹果", "parent_id": 2},
    {"id": 6, "name": "三星", "parent_id": 2},
    {"id": 7, "name": "戴尔", "parent_id": 3},
    {"id": 8, "name": "联想", "parent_id": 3},
    {"id": 9, "name": "小米", "parent_id": 2},
    {"id": 10, "name": "夏普", "parent_id": 4}
]

def get_category_chain(category, chain=None):
    if chain is None:
        chain = []
    chain.insert(0, {"id": category["id"], "name": category["name"]})
    if category["parent_id"]:
        parent_category = next((item for item in category_data if item["id"] == category["parent_id"]), None)
        if parent_category:
            get_category_chain(parent_category, chain)
    return chain

category_id = 8
category = next((item for item in category_data if item["id"] == category_id), None)
category_chain = get_category_chain(category)

category_dict = [menu_to_json(category_chain)]
print(json.dumps(category_dict, ensure_ascii=False, indent=4))

输出结果:

[
    [
        {
            "id": 1,
            "name": "电器",
            "children": [
                {
                    "id": 3,
                    "name": "笔记本电脑",
                    "children": [
                        {
                            "id": 7,
                            "name": "戴尔"
                        },
                        {
                            "id": 8,
                            "name": "联想"
                        }
                    ]
                },
                {
                    "id": 4,
                    "name": "智能电视",
                    "children": [
                        {
                            "id": 10,
                            "name": "夏普"
                        }
                    ]
                },
                {
                    "id": 2,
                    "name": "手机",
                    "children": [
                        {
                            "id": 5,
                            "name": "苹果"
                        },
                        {
                            "id": 9,
                            "name": "小米"
                        },
                        {
                            "id": 6,
                            "name": "三星"
                        }
                    ]
                }
            ]
        },
        {
            "id": 3,
            "name": "笔记本电脑",
            "children": [
                {
                    "id": 7,
                    "name": "戴尔"
                },
                {
                    "id": 8,
                    "name": "联想"
                }
            ]
        },
        {
            "id": 8,
            "name": "联想"
        }
    ]
]

示例2

假设我们有一个课程目录,包含多个课程分类和课程。我们需要按照分类的结构,把课程目录转换成树形结构,并转换成 Json 数据,输出到文件中。示例如下:

class_item_data = [
    {"id": 1, "name": "课程分类1", "parent_id": None},
    {"id": 2, "name": "课程1", "parent_id": 1},
    {"id": 3, "name": "课程2", "parent_id": 1},
    {"id": 4, "name": "课程分类2", "parent_id": None},
    {"id": 5, "name": "课程3", "parent_id": 4},
    {"id": 6, "name": "课程分类1-1", "parent_id": 1},
    {"id": 7, "name": "课程4", "parent_id": 6},
    {"id": 8, "name": "课程分类1-2", "parent_id": 1},
    {"id": 9, "name": "课程5", "parent_id": 8},
    {"id": 10, "name": "课程分类2-1", "parent_id": 4},
    {"id": 11, "name": "课程6", "parent_id": 10},
    {"id": 12, "name": "课程分类2-2", "parent_id": 4},
    {"id": 13, "name": "课程7", "parent_id": 12}
]

class_item_tree = get_menu_children(class_item_data)

class_dict = menu_to_json(class_item_tree)
with open("class_tree.json", 'w', encoding='utf-8') as f:
    f.write(json.dumps(class_dict, ensure_ascii=False, indent=4))

输出结果:使用任意的 JSON 解析工具打开class_tree.json可以看到详细的JSON结构体现了实际的树形结构。

本文链接:http://task.lmcjl.com/news/17283.html

展开阅读全文