【问题标题】:Python json.loads fails with `ValueError: Invalid control character at: line 1 column 33 (char 33)`Python json.loads 因“ValueError: Invalid control character at: line 1 column 33 (char 33)”而失败
【发布时间】:2012-03-06 21:59:07
【问题描述】:

我有一个这样的字符串:

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)

为什么会出现这个错误?我该如何解决这个问题?

【问题讨论】:

标签: python json


【解决方案1】:

也许,另一种选择是使用 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)

【讨论】:

  • 这是一个更好的选择,因为 json 标准允许很少的控制字符。
  • 我同意@shadow0359,这是更好的选择。
  • 这拯救了我的一天!更好的选择 IMO。
【解决方案2】:

问题是您的 unicode 字符串包含回车符 (\r) 和换行符 (\n) JSON 数据中的字符串文字。如果它们是字符串本身的一部分,则应适当地对其进行转义。如果它们不应该成为字符串的一部分,那么它们也不应该出现在您的 JSON 中。

如果您无法修复获取此 JSON 字符串以生成有效 JSON 的位置,您可以删除有问题的字符:

>>> json.loads(s.replace('\r\n', ''))

或手动转义:

>>> json.loads(s.replace('\r\n', '\\r\\n'))

【讨论】:

    【解决方案3】:

    问题在于索引 33 处的字符是回车控制字符。

    >>> s[33]
    u'\r'
    

    根据 JSON 规范,有效字符为:

    • 任何 Unicode 字符,除了:"\ 和控制字符 (ord(char) &lt; 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'}
    

    参考资料:

    【讨论】:

    • 如果字符串在变量中怎么办?例如,我正在接收(通过 HTTP POST)这样的 JSON 对象:{"text": "Hello,\n How are you?"}。我显然不能使用r'' 从中制作原始字符串。我怎样才能要求 Python 如此对待它,还是为时已晚,现在我需要使用某种字符串替换?
    • @orokusaki 如果您收到的 JSON 包含文字控制字符而不是正确的字符序列,那么确实为时已晚,因为 JSON 没有正确生成。因此,如果您无法控制初始生成,则必须在 Python 中进行一些字符串替换。
    • 感谢您的回复。我最终只是将strict=False 传递给loads,我觉得这可能是一个更清洁的解决方案 - 我们会看看它是否会回来咬我:/
    【解决方案4】:

    尝试逃避你的\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得到的一部分,我不知道是否还有其他无效字符。你知道其他无效字符吗?
    【解决方案5】:

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

    【讨论】:

    • 尝试改写你的措辞,以目前的形式更适合作为评论,并以答案的形式散文。描述您认为是什么问题以及您推荐的解决方案。
    • 线程复兴,但 FWIW,这个答案解决了我在搜索中的错误。登录后给您投票。谢谢谢尔顿
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 2016-05-16
    • 2018-08-24
    • 2021-06-11
    • 1970-01-01
    相关资源
    最近更新 更多