首页 > 解决方案 > 使用 Python TTP 解析文本以更正 json

问题描述

假设我有以下文字:

interface GigabitEthernet1/0/1.1
 qinq stacking vid 10 pe-vid 100
 qinq stacking vid 20 pe-vid 100
 qinq stacking vid 30 pe-vid 200
#
interface GigabitEthernet1/0/2.1
 qinq stacking vid 20 pe-vid 200
#

我想使用Template Text Parser解析它。

这是我想要得到的目标 JSON:

[
    {
        "subinterfaces": [
            {
                "interface": "GigabitEthernet1/0/1.1",
                "stacking": {
                    "100": [ "10", "20" ],
                    "200": [ "30" ]
                }
            },
            {
                "interface": "GigabitEthernet1/0/2.1",
                "stacking": {
                    "200": [ "20" ]
                }
            }
        ]
    }
]

我试过这个模板

<group name="subinterfaces">
interface {{ interface | contains('.') }}
<group name="stacking.{{ pevid }}">
 qinq stacking vid {{ vid }} pe-vid {{ pevid }}
 </group>
# {{ _end_ }}
</group>

但它给了我

[
    {
        "subinterfaces": [
            {
                "interface": "GigabitEthernet1/0/1.1",
                "stacking": {
                    "100": [
                        {
                            "vid": "10"
                        },
                        {
                            "vid": "20"
                        }
                    ],
                    "200": {
                        "vid": "30"
                    }
                }
            },
            {
                "interface": "GigabitEthernet1/0/2.1",
                "stacking": {
                    "200": {
                        "vid": "20"
                    }
                }
            }
        ]
    }
]

使用“|”应用于vid的任何修饰符/函数 (管)没有任何作用。

这个问题背后的动机是学习 TTP 机制。请不要使用其他工具发送答案。

标签: pythonjsonparsing

解决方案


这是一个有趣的问题,但是不存在匹配变量或组函数来满足在列表中组合匹配项同时{{ match }}在一行上定义多个变量的要求。存在joinmatches功能,但由于特定原因,它在这里不起作用。

我能想到的最好的结果是使用 Python 进行结果后处理。

例如,此模板post_processing使用宏标签定义 Python 函数,并使用输出标签通过它传递结果:

<group name="subinterfaces">
interface {{ interface | contains('.') }}
 <group name="stacking.{{ pevid }}.{{ vid }}">
 qinq stacking vid {{ vid }} pe-vid {{ pevid }}
 </group>
# {{ _end_ }}
</group>

<output macro="post_process"/>

<macro>
def post_process(data):
    for item in data[0]["subinterfaces"]:
        item["stacking"] = {
            k: list(v.keys()) for k, v in item["stacking"].items()
        }
    return(data)
</macro>

subinterfaces组被修改以产生这些结果:

[
    [
        {
            "subinterfaces": [
                {
                    "interface": "GigabitEthernet1/0/1.1",
                    "stacking": {
                        "100": {
                            "10": {},
                            "20": {}
                        },
                        "200": {
                            "30": {}
                        }
                    }
                },
                {
                    "interface": "GigabitEthernet1/0/2.1",
                    "stacking": {
                        "200": {
                            "20": {}
                        }
                    }
                }
            ]
        }
    ]
]

在使用宏通过输出器传递上述数据后post_processing,结果转换为所需的结构:

[
    [
        {
            "subinterfaces": [
                {
                    "interface": "GigabitEthernet1/0/1.1",
                    "stacking": {
                        "100": [
                            "10",
                            "20"
                        ],
                        "200": [
                            "30"
                        ]
                    }
                },
                {
                    "interface": "GigabitEthernet1/0/2.1",
                    "stacking": {
                        "200": [
                            "20"
                        ]
                    }
                }
            ]
        }
    ]
]

推荐阅读