在python中使用递归操作json

2024-09-28 23:13:06 发布

您现在位置:Python中文网/ 问答频道 /正文

全部

我试图通过以下方式对一些json进行检查和格式化,来改变它的外观:

1. flatten all of the fields lists
2. Then remove the fields lists and replace them with the name : flatten list

示例:

{
"name": "",
"fields": [{
        "name": "keys",
        "fields": [{
                "node-name": "0/0/CPU0"
            },
            {
                "interface-name": "TenGigE0/0/0/47"
            },
            {
                "device-id": "ASR9K-H1902.corp.cisco.com"
            }
        ]
    },
    {
        "name": "content",
        "fields": [{
            "name": "lldp-neighbor",
            "fields": [{
                    "receiving-interface-name": "TenGigE0/0/0/47"
                },
                {
                    "receiving-parent-interface-name": "Bundle-Ether403"
                },
                {
                    "device-id": "ASR9K-H1902.corp.cisco.com"
                },
                {
                    "chassis-id": "78ba.f975.a64f"
                },
                {
                    "port-id-detail": "Te0/1/0/4/0"
                },
                {
                    "header-version": 0
                },
                {
                    "hold-time": 120
                },
                {
                    "enabled-capabilities": "R"
                },
                {
                    "platform": ""
                }
            ]
        }]
    }
]
}

会变成:

{
"": [{

        "keys": [{
            "node-name": "0/0/CPU0",
            "interface-name": "TenGigE0/0/0/47",
            "device-id": "ASR9K-H1902.corp.cisco.com"
        }]
    },
    {
        "content": [{
            "lldp-neighbor": [{
                "receiving-interface-name": "TenGigE0/0/0/47",
                "receiving-parent-interface-name": "Bundle-Ether403",
                "device-id": "ASR9K-H1902.corp.cisco.com",
                "chassis-id": "78ba.f975.a64f",
                "port-id-detail": "Te0/1/0/4/0",
                "header-version": 0,
                "hold-time": 120,
                "enabled-capabilities": "R",
                "platform": ""
            }]
        }]
    }
]
}

我尝试了以下方法使列表扁平化:

def _flatten_fields(self, fields_list):
        c = {}
        for b in [d for d in fields_list if bool(d)]:
                c.update(b)
        return c

这似乎是可行的,但我无法找到一种方法进入子级别使用递归,我保存所有扁平列表和名称到一个新的字典,有没有办法做到这一点,只是操纵原来的字典?你知道吗


Tags: thenamecomidfieldsdeviceciscointerface
2条回答

这对您提供的示例有效:

import json

def flatten(data):
    result = dict()
    if isinstance(data, dict):
        if 'name' in data:
            name = data['name']
            result[name] = flatten(data['fields'])
        else:
            key = data.keys()[0]
            value = data.values()[0]
            result[key] = value
    else:
        for entry in data:
            result.update(flatten(entry))
    return result

print json.dumps(flatten(data), indent=4)

输出

{
    "": {
        "keys": {
            "node-name": "0/0/CPU0", 
            "interface-name": "TenGigE0/0/0/47", 
            "device-id": "ASR9K-H1902.corp.cisco.com"
        }, 
        "content": {
            "lldp-neighbor": {
                "receiving-interface-name": "TenGigE0/0/0/47", 
                "receiving-parent-interface-name": "Bundle-Ether403", 
                "header-version": 0, 
                "port-id-detail": "Te0/1/0/4/0", 
                "chassis-id": "78ba.f975.a64f", 
                "platform": "", 
                "device-id": "ASR9K-H1902.corp.cisco.com", 
                "hold-time": 120, 
                "enabled-capabilities": "R"
            }
        }
    }
}

它没有在您期望的输出中显示额外的list层,但我认为您不需要这些。你知道吗

这对您提供的示例有效:

def flatten_fields(fields_list):

    c = {}
    for item in fields_list:
        for key in item:
            if key == "fields":
                c[item["name"]] = flatten_fields(item["fields"])
            elif key != "name":
                c[key] = item[key]
            break

    return [c]

但是它在字典列表上工作,所以您应该像flatten_fields([data])[0]那样调用它。你知道吗

输出为:

{
"": [{
    "keys": [{
        "node-name": "0/0/CP0", 
        "interface-name": "TenGigE0/0/0/47", 
        "device-id": "ASR9K-H1902.corp.cisco.com"
        }], 
    "content": [{
        "lldp-neighbor": [{
            "chassis-id": "78ba.f975.a64f", 
            "receiving-parent-interface-name": "Bndle-Ether403", 
            "enabled-capabilities": "R", 
            "device-id": "ASR9K-H1902.corp.cisco.com", 
            "hold-time": 120, 
            "receiving-interface-name": "TenGigE0/0/0/47", 
            "platform": "", 
            "header-version": 0, 
            "port-id-detail": "Te0/1/0/4/0"
            }]
        }]
    }]
}

相关问题 更多 >