将丑陋的字符串(自定义非json格式)转换为字典

问题描述 投票:2回答:2

我有这个字符串我想加载为字典,以便我可以访问每个项目。

my_str = "[
    id=xyz-111,
    abc= {
            item=[
                    {
                        a=xyz,
                        b=123,
                        c={},
                        d={
                        i=[{ip=0.0.0.0/0}]
                            },
                    }
            ]
    }
]"

目前我正在使用正则表达式(re library)来获取字符串中任何项的值,这是有效的。

有没有更简洁的方法将此字符串转换为字典?我尝试过json.loads()ast不起作用。

预期结果:

my_dict = {
    'id':'xyz-111',
    'abc': {
            'item':[
                    {
                        'a':'xyz',
                        'b':123,
                        'c':{},
                        'd':{
                        'i':[{'ip':'0.0.0.0/0'}]
                            },
                    }
            ]
    }
}
python python-3.x dictionary string-conversion
2个回答
3
投票

嗯,这非常难看,但它可能会为您提供一个创建更有效解决方案的起点。基本上,一系列替换,第一个包括切片和用dict闭合替换开口和闭合括号。然后,ast.literal_eval转换为dict。

import ast
import re

s = """
[
    id=xyz-111,
    abc= {
      item=[
        {
          a=xyz,
          b=123,
          c={},
          d={
            i=[{ip=0.0.0.0/0}]
          },
        }
      ]
    }
]
"""

a = '{' + re.sub(r'=', r':', re.sub(r'\s+', '', s))[1:-1] + '}'
b = re.sub(r'([{}[\]:,])([^{}[\]:,])', r'\1"\2', a)
c = re.sub(r'([^{}[\]:,])([{}[\]:,])', r'\1"\2', b)
d = ast.literal_eval(c)

print(d)
# {'id': 'xyz-111', 'abc': {'item': [{'a': 'xyz', 'b': '123', 'c': {}, 'd': {'i': [{'ip': '0.0.0.0/0'}]}}]}}
  • a删除所有空格,用=替换:,并用[]替换外部{}(空白删除是一种钝器,如果数据包含需要保留空格的字符串,则需要更具体针对性)
  • b在括号,分号或逗号之后插入",后面没有任何字符
  • qazxsw poi在括号,分号或逗号之前插入qazxsw poi,前面没有任何这些字符
  • c使用"将字符串转换为dict,这比d稍微宽容一些

0
投票

我同意你的观点,通常ast.literal_eval将成为摄取它的首选。这个字符串来自哪里?

proper solution

似乎某些代码的layer_1生成了格式良好的JSON,然后layer_2删除了引号。找到layer_2,告诉它停止这样做。或者,复制layer_2,让您自己的代码使用原始输入并更好地处理它,因此引号不会丢失。

hackish solution

当然,在标点符号和行结尾之间仍然存在一些结构,因此在最坏情况下,将UnStrip例程放回到缺失的引号中是值得的。例如,在例如json.loads,发出json.loads()并不是那么糟糕,因为你可以随时发布进程,你递归地尝试将字典值转换为数字,使用b=123 / 'b':'123'忽略错误,如果值看起来更像try而不是一些整数。

实际上,在except中包装'xyz'的例子是有益的。在输入的任何给定行中可能存在一些歧义,可以选择将变量A或​​B作为有效的JSON。尝试两者,包装在n = float(s)中,并返回第一个获胜,第一个评估为有效JSON的可能是有用的。

© www.soinside.com 2019 - 2024. All rights reserved.