Python json.loads 失败,出现 `ValueError: 无效的控制字符:第1行 第33列 (字符33)`
我有一个这样的字符串:
s = u"""{"desc": "\u73cd\u54c1\u7f51-\u5168\u7403\u6f6e\u6d41\u5962\u54c1\u7f51\u7edc\u96f6\u552e\u5546 <br \/>\r\nhttp:\/\/www.zhenpin.com\/ <br \/>\r\n<br \/>\r\n200\u591a\u4e2a\u56fd\u9645\u4e00\u7ebf\u54c1\u724c\uff0c\u9876\u7ea7\u4e70\u624b\u5168\u7403\u91c7\u8d2d\uff0c100%\u6b63\u54c1\u4fdd\u969c\uff0c7\u5929\u65e0\u6761\u2026"}"""
json.loads(s)
会返回这样的错误信息:
ValueError: Invalid control character at: line 1 column 33 (char 33)
为什么会出现这个错误呢?我该怎么解决这个问题?
5 个回答
12
问题是索引为33的字符是一个回车控制字符。
>>> s[33]
u'\r'
根据JSON的规范,有效的字符包括:
任何Unicode字符,除了:
"
、\
和控制字符(ord(char) < 32
)。以下字符序列是允许的:
\"
、\\
、\/
、\b
(退格)、\f
(换页)、\n
(换行)、\r
(回车)、\t
(制表符),或者\u
后面跟着四个十六进制数字。
不过,在Python中,你需要对控制字符进行双重转义(除非字符串是原始字符串),因为Python也会解释这些控制字符。
>>> s = ur"""{"desc": "\u73cd\u54c1\u7f51-\u5168\u7403\u6f6e\u6d41\u5962\u54c1\u7f51\u7edc\u96f6\u552e\u5546 <br \/>\r\nhttp:\/\/www.zhenpin.com\/ <br \/>\r\n<br \/>\r\n200\u591a\u4e2a\u56fd\u9645\u4e00\u7ebf\u54c1\u724c\uff0c\u9876\u7ea7\u4e70\u624b\u5168\u7403\u91c7\u8d2d\uff0c100%\u6b63\u54c1\u4fdd\u969c\uff0c7\u5929\u65e0\u6761\u2026"}"""
>>> json.loads(s)
{u'desc': u'\u73cd\u54c1\u7f51-\u5168\u7403\u6f6e\u6d41\u5962\u54c1\u7f51\u7edc\u96f6\u552e\u5546 <br />\r\nhttp://www.zhenpin.com/ <br />\r\n<br />\r\n200\u591a\u4e2a\u56fd\u9645\u4e00\u7ebf\u54c1\u724c\uff0c\u9876\u7ea7\u4e70\u624b\u5168\u7403\u91c7\u8d2d\uff0c100%\u6b63\u54c1\u4fdd\u969c\uff0c7\u5929\u65e0\u6761\u2026'}
参考资料:
127
还有一个选择,也许是使用 strict=False
这个参数。
根据 这个链接 的说明:
“如果 strict 设置为 False(默认是 True),那么字符串里面就可以包含控制字符。这里提到的控制字符是指那些字符编码在 0 到 31 范围内的字符,比如 '\t'(制表符)、'\n'(换行符)、'\r'(回车符)和 '\0'。”
举个例子:
json.loads(json_str, strict=False)
69
问题在于你的unicode字符串里面包含了回车符(\r
)和换行符(\n
),而这些符号是在JSON数据的字符串字面量中出现的。如果这些符号是想要作为字符串的一部分,那就需要正确地进行转义。如果它们不是字符串的一部分,那它们就不应该出现在你的JSON里。
如果你无法修复生成这个JSON字符串的地方,使其变成有效的JSON,你可以选择去掉这些多余的字符:
>>> json.loads(s.replace('\r\n', ''))
或者手动进行转义:
>>> json.loads(s.replace('\r\n', '\\r\\n'))