修复类似JSON的文件中的未加引号的键,以便它使用正确的JSON语法

时间:2015-06-24 14:26:51

标签: python regex json

我有一个非常大的类似JSON的文件,但它没有使用正确的JSON语法:没有引用对象键。我想编写一个脚本来修复文件,以便我可以使用json.loads加载它。

我需要匹配后跟冒号的所有单词,并用引用的单词替换它们。我认为正则表达式是\w+\s*:,我应该使用re.sub,但我不确定该怎么做。

如何获取以下输入并获得给定的输出?

# In
{abc : "xyz", cde : {}, fgh : ["hfz"]}
# Out
{"abc" : "xyz", "cde" : {}, "fgh" : ["hfz"]}

# In
{
    a: "b",
    b: {
        c: "d",
        d: []
    },
    e: "f"
}
# Out
{
    "a": "b",
    "b": {
        "c": "d",
        "d": []
    },
    "e": "f"
}

3 个答案:

答案 0 :(得分:9)

您可以利用以下事实:您的日志文件不是有效的JSON,而 有效YAML,而不是可能非常脆弱的正则表达式解决方案。使用PyYAML库,您可以将其加载到Python数据结构中,然后将其作为有效的JSON写回:

import json
import yaml

with open("original.log") as f:
    data = yaml.load(f)

with open("jsonified.log", "w") as f:
    json.dump(data, f)

答案 1 :(得分:2)

我建议将未包含在双引号中的整个单词匹配,并在它们周围添加引号:

import re
p = re.compile(r'(?<!")\b\w+\b(?!")')
test_str = "{abc : \"xyz\", cde : {}, fgh : [\"hfz\"]}"
print re.sub(p, r'"\g<0>"', test_str)

请参阅IDEONE demo,输出:

{"abc" : "xyz", "cde" : {}, "fgh" : ["hfz"]}

答案 2 :(得分:0)

我在寻找将邋J的JSON速记解析为python的方法时遇到了这个老问题。

我的输入如下:

'{lat: 8.5, lon: -80.0}'

而且,正如所说的那样,它必须是宽松的空间,它也可以是:

'{lat:8.5,lon:-80.0}'

我喜欢YAML提示,但是它与间距不合适并不顺利,我不希望在我已经很长的列表中添加一个依赖项,所以我尝试了正则表达式解决方案,但这还不够好对于我的情况。

我的解决方案如下:

re.sub(r'(\w+)[ ]*(?=:)', r'"\g<1>"', input_string)

它定义了一个组,包含字母数字数据,它允许跟随空格,它锚定到分号,它用第一组替换匹配的子字符串,用双引号括起来。所有其余的都是独自留下的。如果已经引用了密钥,则该模式将不匹配。

特别是:

>>> re.sub(r'(\w+)[ ]*(?=:)', r'"\g<1>"', 
... '{abc : "xyz", cde : {a:"b", c: 0}, fgh : ["hfz"], 123: 123}')
'{"abc": "xyz", "cde": {"a":"b", "c": 0}, "fgh": ["hfz"], "123": 123}'
>>> re.sub(r'(\w+)[ ]*(?=:)', r'"\g<1>"', _)
'{"abc": "xyz", "cde": {"a":"b", "c": 0}, "fgh": ["hfz"], "123": 123}'
>>>