如何自动修复无效的JSON字符串?

从2gis API中,我得到了以下JSON字符串。

{
    "api_version": "1.3",
    "response_code": "200",
    "id": "3237490513229753",
    "lon": "38.969916127827",
    "lat": "45.069889625267",
    "page_url": null,
    "name": "ATB",
    "firm_group": {
        "id": "3237499103085728",
        "count": "1"
    },
    "city_name": "Krasnodar",
    "city_id": "3237585002430511",
    "address": "Turgeneva,   172/1",
    "create_time": "2008-07-22 10:02:04 07",
    "modification_time": "2013-08-09 20:04:36 07",
    "see_also": [
        {
            "id": "3237491513434577",
            "lon": 38.973110606808,
            "lat": 45.029031222211,
            "name": "Advance",
            "hash": "5698hn745A8IJ1H86177uvgn94521J3464he26763737242Cf6e654G62J0I7878e",
            "ads": {
                "sponsored_article": {
                    "title": "Center "ADVANCE"",
                    "text": "Business.English."
                },
                "warning": null
            }
        }
    ]
}

但是Python不承认它:

json.loads(firm_str)

期望,定界符:第1行3646(char 3645)

它看起来像引用中的问题:“title”:“Center”ADVANCE“”

我如何在Python中自动修复它?


@Michael的回答给了我一个想法...不是一个非常漂亮的想法,但它似乎工作,至少在你的例子:尝试解析JSON字符串,如果失败,寻找失败的字符异常字符串并替换该字符。

while True:
    try:
        result = json.loads(s)   # try to parse...
        break                    # parsing worked -> exit loop
    except Exception as e:
        # "Expecting , delimiter: line 34 column 54 (char 1158)"
        # position of unexpected character after '"'
        unexp = int(re.findall(r'(char (d+))', str(e))[0])
        # position of unescaped '"' before that
        unesc = s.rfind(r'"', 0, unexp)
        s = s[:unesc] + r'"' + s[unesc+1:]
        # position of correspondig closing '"' (+2 for inserted '')
        closg = s.find(r'"', unesc + 2)
        s = s[:closg] + r'"' + s[closg+1:]
print result

您可能需要添加一些额外的检查,以防止这种情况在无限循环中结束(例如,最多与字符串中的字符一样多的重复)。 而且,如果@gnibbler指出错误的"实际上后面跟着一个逗号,这仍然不起作用。

更新:现在看起来工作得很好(虽然仍然不完美),即使非转义的"后面跟着逗号或右括号,因为在这种情况下,它可能会在此之后得到关于语法错误的投诉(预期属性名称等)并追溯到最后" 。 它也会自动转义相应的结尾" (假设有一个)。


如果这正是API返回的内容,那么他​​们的API存在问题。 这是无效的JSON。 特别是在这个领域:

"ads": {
            "sponsored_article": {
                "title": "Образовательный центр "ADVANCE"", <-- here
                "text": "Бизнес.Риторика.Английский язык.Подготовка к школе.Подготовка к ЕГЭ."
            },
            "warning": null
        }

ADVANCE周围的双引号不会被转义。 你可以通过使用像http://jsonlint.com/来验证它。

这是一个问题, "没有被转义,如果这是你所得到的,数据在源头上是不好的,他们需要修复它。

Parse error on line 4:
...азовательный центр "ADVANCE"",         
-----------------------^
Expecting '}', ':', ',', ']'

这解决了这个问题:

"title": "Образовательный центр "ADVANCE"",

唯一真正的和确定的解决方案是2gis修复他们的API。

与此同时,可以修复字符串内严重编码的JSON转义双引号。 如果每个键值对都跟着一个换行符(因为它似乎来自发布的数据),下面的函数将完成这项工作:

def fixjson(badjson):
    s = badjson
    idx = 0
    while True:
        try:
            start = s.index( '": "', idx) + 4
            end1  = s.index( '",n',idx)
            end2  = s.index( '"n', idx)
            if end1 < end2:
                end = end1
            else:
                end = end2
            content = s[start:end]
            content = content.replace('"', '"')
            s = s[:start] + content + s[end:]
            idx = start + len(content) + 6
        except:
            return s

请注意一些暗示:

该函数试图在属于键值对的值字符串中转义双引号字符。

假定要在该序列之后开始转义的文本

": "

并在序列之前结束

",n

要么

"n

将发布的JSON传递给该函数会导致返回的值

{
    "api_version": "1.3",
    "response_code": "200",
    "id": "3237490513229753",
    "lon": "38.969916127827",
    "lat": "45.069889625267",
    "page_url": null,
    "name": "ATB",
    "firm_group": {
        "id": "3237499103085728",
        "count": "1"
    },
    "city_name": "Krasnodar",
    "city_id": "3237585002430511",
    "address": "Turgeneva,   172/1",
    "create_time": "2008-07-22 10:02:04 07",
    "modification_time": "2013-08-09 20:04:36 07",
    "see_also": [
        {
            "id": "3237491513434577",
            "lon": 38.973110606808,
            "lat": 45.029031222211,
            "name": "Advance",
            "hash": "5698hn745A8IJ1H86177uvgn94521J3464he26763737242Cf6e654G62J0I7878e",
            "ads": {
                "sponsored_article": {
                    "title": "Center "ADVANCE"",
                    "text": "Business.English."
                },
                "warning": null
            }
        }
    ]
}

请记住,如果您的需求未得到充分满足,您可以轻松定制该功能。

链接地址: http://www.djcxy.com/p/48675.html

上一篇: How do I automatically fix an invalid JSON string?

下一篇: TypeError: write() argument must be str, not bytes (Python 3 vs Python 2 )