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

2024-06-07 19:13:23 发布

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

从2gisapi中,我得到了以下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)

Expecting , delimiter: line 1 column 3646 (char 3645)

以下引用似乎有问题: “title”:“中心”前进

如何在Python中自动修复它?


Tags: 字符串nameapiidjsoncitytimetitle
3条回答

如果这正是API返回的内容,那么它们的API就有问题。这是无效的JSON。尤其是在这个地区:

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

预付款周围的双引号没有漏掉。你可以通过使用http://jsonlint.com/之类的东西来验证它。

这是一个"未转义的问题,如果这是您得到的,则数据在源位置不正确。他们需要修理它。

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

这解决了问题:

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

那个answer by @Michael给了我一个主意。。。这不是一个很好的主意,但至少在您的示例中似乎是可行的:尝试解析JSON字符串,如果失败,在异常字符串1中查找失败的字符并替换该字符。

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指出的那样。

更新:这似乎很管用(尽管仍然不完美),即使未转义的"后面跟逗号或右括号,在本例中,它可能会收到关于其后语法错误(预期的属性名等)的投诉,并追溯到最后一个"。它还会自动转义相应的结束"(假设有一个)。


1)异常的str"Expecting , delimiter: line XXX column YYY (char ZZZ)",其中ZZZ是发生错误的字符串中的位置。不过,请注意,此消息可能取决于Python的版本、json模块、操作系统或区域设置,因此可能必须相应地调整此解决方案。

唯一真正和确定的解决方案是让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
            }
        }
    ]
}

请记住,如果您的需求没有完全满足,您可以很容易地定制功能。

相关问题 更多 >

    热门问题