从本文中提取所有json字符串,返回字典组成的列表

有些命令行可以返回json格式的输出,比如openstack的cli命令、iperf3,我们可以去除输出中前后和中间多余的内容,
提取出json字符串,转换成字典,方便后续操作其中的内容。
实现下面的函数完成这项工作。
不论命令是执行在物理服务器、虚拟机服务器、网络设备上,也不论是在ssh/telnet vty上执行,
还是console或者本地shell上执行,也不论是一条命令的输出,还是一组命令的输出,
只要输出中有json字符串,就可以将输出传入下面的函数中,得到字典。
这里所说的json字符串之外的多余的内容,可能是设备的prompt、输入的(其它)命令以及它们的输出。
其实,这个函数本身不在意输入的text是如何得来的,分析cli的输出只是一种使用场景。

源代码:

#python3.8
#coding=utf-8
#author=liuyifan

import json

'''
初步版本:只能提取文本中唯一的json字符串
从文本中提取出json字符串,首先去除前后多余的内容,然后将其转换成字典返回。
局限:文本中只能有一个json字符串,该json字符串前后的内容中不能有{和}。
说明:json字符串内部还有{和}不影响提取和解析。JSON字符串前后没有多余内容时也能正常提取和解析。
'''
def convert_json_in_text_to_dict(text):
    # 去除{之前的多余内容,这条语句同时适用于{之前没有多余内容的情况
    t = text[len(text.split('{')[0]):]
    suffix_length = len(text.split('}')[-1])
    # 去除}之后的多余内容, }之后没有多余内容时,则不用处理
    if suffix_length:
        t = t[:-suffix_length]
    # 转换成字典返回
    return json.loads(t)

'''
进阶版本:能提取任意多个json字符串。
从文本中提取出所有json字符串,将它们转换成字典,最后返回字典组成的列表。
说明:输入的文本中可以有不属于任何json字符串的内容,
但是这些内容中不能有{和},否则可能影响json字符串的定界。
文本中可以有多个json字符串。
json字符串内部可以嵌套成对的{}。但是不能有不成对的{或者}。
实现说明:这里用栈的来匹配左右花括号,从而定界每一个json字符串。
按index遍历输入的文本,每到遇到{,则将其index入栈,每当遇到},则弹出栈内的一个{,
如果弹出后栈为空了,说明到了一个json字符串的结尾。
而刚刚弹出的元素值就是这个json字符串的开始位置。
'''
def convert_all_json_in_text_to_dict(text):
    dicts, stack = [], []
    for i in range(len(text)):
        if text[i] == '{':
            stack.append(i)
        elif text[i] == '}':
            begin = stack.pop()
            if not stack:
                dicts.append(json.loads(text[begin:i+1]))
    return dicts

# 看一下执行效果
text1='''
ab: cd
{
    "network": {
        "name": "net101",
        "admin_state_up": true,
        "segments": [
            {
                "provider:segmentation_id": 5,
                "provider:physical_network": "public",
                "provider:network_type": "vlan"
            },
            {
                "provider:physical_network": "default",
                "provider:network_type": "flat"
            }
        ]
    }
}
ef> gh
'''

import pprint
d = convert_json_in_text_to_dict(text1)
print(type(d))
pprint.pprint(d)
pprint.pprint(d["network"]["segments"])


text2='''
ab: cd
{
    "network": {
        "name": "net101",
        "admin_state_up": true,
        "segments": [
            {
                "provider:segmentation_id": 5,
                "provider:physical_network": "public",
                "provider:network_type": "vlan"
            },
            {
                "provider:physical_network": "default",
                "provider:network_type": "flat"
            }
        ]
    }
}
ef> gh
{
    "students": [
    { "name":"Tom" , "age":18 }, 
    { "name":"Lily" , "age":19 }
    ]
}
HIJK#
'''

ds = convert_all_json_in_text_to_dict(text2)
print("---------------------------convert_all_json_in_text_to_dict()的输出----------------------------------------------")
pprint.pprint(ds)
print(type(ds[0]))
pprint.pprint(ds[0])
pprint.pprint(ds[0]["network"]["segments"])
pprint.pprint(ds[1])

输出:

<class 'dict'>
{'network': {'admin_state_up': True,
             'name': 'net101',
             'segments': [{'provider:network_type': 'vlan',
                           'provider:physical_network': 'public',
                           'provider:segmentation_id': 5},
                          {'provider:network_type': 'flat',
                           'provider:physical_network': 'default'}]}}
[{'provider:network_type': 'vlan',
  'provider:physical_network': 'public',
  'provider:segmentation_id': 5},
 {'provider:network_type': 'flat', 'provider:physical_network': 'default'}]
---------------------------convert_all_json_in_text_to_dict()的输出----------------------------------------------
[{'network': {'admin_state_up': True,
              'name': 'net101',
              'segments': [{'provider:network_type': 'vlan',
                            'provider:physical_network': 'public',
                            'provider:segmentation_id': 5},
                           {'provider:network_type': 'flat',
                            'provider:physical_network': 'default'}]}},
 {'students': [{'age': 18, 'name': 'Tom'}, {'age': 19, 'name': 'Lily'}]}]
<class 'dict'>
{'network': {'admin_state_up': True,
             'name': 'net101',
             'segments': [{'provider:network_type': 'vlan',
                           'provider:physical_network': 'public',
                           'provider:segmentation_id': 5},
                          {'provider:network_type': 'flat',
                           'provider:physical_network': 'default'}]}}
[{'provider:network_type': 'vlan',
  'provider:physical_network': 'public',
  'provider:segmentation_id': 5},
 {'provider:network_type': 'flat', 'provider:physical_network': 'default'}]
{'students': [{'age': 18, 'name': 'Tom'}, {'age': 19, 'name': 'Lily'}]}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值