Python 的 json.loads 出现 `ValueError: Invalid control character at: line 1 column 33 (char 33)` 错误

58

我有一个这样的字符串:

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个回答

127
另一个选择是使用strict=False参数。根据http://docs.python.org/2/library/json.html,“如果 strict 为 False(默认为 True),则允许在字符串内包含控制字符。在此上下文中,控制字符是指字符代码在 0-31 范围内的字符,包括 '\t'(制表符)、'\n'、'\r' 和 '\0'。”例如:
json.loads(json_str, strict=False)

6
这是更好的选择,因为 JSON 标准允许少量控制字符。 - ns15

69
问题出在你的Unicode字符串中包含了回车符(\r)和换行符(\n),它们在JSON数据的字符串字面量内。如果它们应该是字符串本身的一部分,那么应适当进行转义。如果它们不应该是字符串的一部分,那么它们也不应该在你的JSON数据中。
如果你无法修改JSON字符串以生成有效的JSON格式,那么你可以删除这些有问题的字符:
>>> json.loads(s.replace('\r\n', ''))
或者手动转义它们:
>>> json.loads(s.replace('\r\n', '\\r\\n'))

12
问题在于索引 33 处的字符是回车控制字符。
>>> s[33]
u'\r'

根据JSON规范,有效字符如下:
  • 除了以下控制字符(ord(char) < 32),任何Unicode字符都是允许的:"\

  • 以下字符序列是被允许的:\"\\\/\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'}

References:


2
如果字符串在变量中怎么办?例如,我通过HTTP POST接收到一个JSON对象,如下所示:{"text": "Hello,\n How are you?"}。显然,我不能使用r''将其转换为原始字符串。我该如何让Python将其视为原始字符串,还是现在太晚了,现在需要使用某种字符串替换方法? - orokusaki
1
如果你收到的JSON中包含了字面控制字符而不是正确的字符序列,那么就太晚了,因为JSON没有被正确生成。所以如果你无法控制初始生成,你就需要在Python中进行一些字符串替换。@orokusaki - Uyghur Lives Matter
谢谢你的回复。我最终只是向loads传递了strict=False,我觉得这可能是一个更干净的解决方案 - 看看是否会有问题 :/ - orokusaki

8
尝试转义您的\n\r
s = s.replace('\r', '\\r').replace('\n', '\\n')
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'}

这是我从另一个网站的API中获取的一部分内容,我不知道是否还有其他无效字符。你知道其他无效字符吗? - 福气鱼

0
在某些情况下,当文件实际上包含一个带有空格的字符串时,会引发此错误。删除空格将解决问题。

尝试重新书写你的措辞,目前的形式更适合作为评论,将其改写成回答的形式。描述你认为存在的问题以及你推荐的解决方案。 - Mike McMahon
1
线程复活,但是就我个人而言,这个答案解决了我在搜索中遇到的错误。登录以给你投票。谢谢 Sheldon。 - Jordan Wayne Crabb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接