Python的json.loads失败与'ValueError:无效的控制字符:行1列33(char 33)`

我有这样的string:

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) 

为什么会发生这种错误? 我该如何解决这个问题?

问题是你的unicodestring包含在JSON数据中的string文字中的回车符( \r )和换行符( \n )。 如果它们本身就是string的一部分,就应该适当地逃脱。 如果他们不是string的一部分,他们也不应该在你的JSON中。

如果您无法修复您获取此JSONstring以生成有效JSON的位置,则可以删除违规字符:

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

或手动转义它们:

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

另一种select也许是使用strict=False参数

根据http://docs.python.org/2/library/json.html

“如果strict是False(True是默认值),那么控制字符将被允许在string中。在这个上下文中的控制字符是字符代码在0-31范围内的字符,包括'\ t'(tab),'\ n ','\ r'和'\ 0'。“

例如:

 json.loads(json_str, strict=False) 

问题是索引33处的字符是一个回车控制字符。

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

根据JSON规范,有效的字符是:

  • 任何Unicode字符,除了:, \和控制字符( ord(char) < 32 )。

  • 允许使用以下字符序列: \\\\\\\\ \b (退格), \f (换页) \n (换行/换行) \r (回车) \t (制表符)或\u后跟四个hex数字。

然而,在Python中,你将不得不双重转义控制字符(除非string是原始的),因为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'} 

参考文献:

尝试逃避\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'} 

在某些情况下,如果文件实际上包含一个带有空格的string,则会引发此错误。 删除空白将解决问题。