Python: json.loads 函数处理转义字符时出错

31 投票
3 回答
58345 浏览
提问于 2025-04-15 14:43

我有一个应用程序,它把一个JSON对象(用Prototype格式化)发送到一个ASP服务器。在服务器上,Python 2.6的“json”模块试图加载这个JSON,但在处理某些反斜杠的组合时出现了问题。你看:

>>> s
'{"FileExists": true, "Version": "4.3.2.1", "Path": "\\\\host\\dir\\file.exe"}'

>>> tmp = json.loads(s)
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  {... blah blah blah...}
  File "C:\Python26\lib\json\decoder.py", line 155, in JSONString
    return scanstring(match.string, match.end(), encoding, strict)
  ValueError: Invalid \escape: line 1 column 58 (char 58)

>>> s[55:60]
u'ost\\d'

在第58列是转义的反斜杠。我以为这个转义是正确的!UNC路径是\\host\dir\file.exe,所以我只是把斜杠加倍了。但是显然这样不行。有人能帮忙吗?作为最后的办法,我在考虑把反斜杠转换成斜杠,然后再转换回来,但我觉得这真的是个临时的解决办法。

提前谢谢大家!

3 个回答

0
>>> s
'{"FileExists": true, "Version": "4.3.2.1", "Path": "\\\\host\\dir\\file.exe"}'
>>> print s
{"FileExists": true, "Version": "4.3.2.1", "Path": "\\host\dir\file.exe"}

你其实并没有正确处理这个字符串,所以它在尝试解析一些无效的转义代码,比如 \d\f。建议你使用一个经过充分测试的 JSON 编码器,比如 json2.js

20

因为这个错误提示会告诉你出错的转义字符的位置,所以我开发了一个小技巧,可能会对你有帮助 :)

def fix_JSON(json_message=None):
    result = None
    try:        
        result = json.loads(json_message)
    except Exception as e:      
        # Find the offending character index:
        idx_to_replace = int(str(e).split(' ')[-1].replace(')', ''))        
        # Remove the offending character:
        json_message = list(json_message)
        json_message[idx_to_replace] = ' '
        new_message = ''.join(json_message)     
        return fix_JSON(json_message=new_message)
    return result
34

正确的 JSON 格式是:

r'{"FileExists": true, "Version": "4.3.2.1", "Path": "\\\\host\\dir\\file.exe"}'

注意字母 r,如果你省略了它,那么在 Python 中你也需要对 \ 进行转义。

>>> import json
>>> d = json.loads(s)
>>> d.keys()
[u'FileExists', u'Path', u'Version']
>>> d.values()
[True, u'\\\\host\\dir\\file.exe', u'4.3.2.1']

注意这个区别:

>>> repr(d[u'Path'])
"u'\\\\\\\\host\\\\dir\\\\file.exe'"
>>> str(d[u'Path'])
'\\\\host\\dir\\file.exe'
>>> print d[u'Path']
\\host\dir\file.exe

在 Python 的 REPL(交互式解释器)中,默认情况下会打印对象 objrepr(obj) 表示:

>>> class A:
...   __str__ = lambda self: "str"
...   __repr__  = lambda self: "repr"
... 
>>> A()
repr
>>> print A()
str

所以你最开始的 s 字符串在 JSON 格式上是不正确的。它包含了没有转义的 '\d''\f'print s 必须显示 '\\d',否则就不是正确的 JSON。

注意:JSON 字符串是一组零个或多个 Unicode 字符,用双引号包裹,并使用反斜杠进行转义(json.org)。在上面的例子中,我省略了编码问题(也就是字节字符串和 Unicode 之间的转换)。

撰写回答