Python json.loads терпит неудачу с `ValueError: Invalid control character at: строка 1 столбец 33 (char 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)
Почему эта ошибка возникает? Как я могу решить эту проблему?
Ответы
Ответ 1
Проблема заключается в том, что ваша строка в Юникоде содержит возвращаемые каретки (\r
) и новые строки (\n
) в строковом литерале в данных JSON. Если они должны были быть частью самой строки, они должны быть экранированы соответствующим образом. Если они не должны были быть частью строки, они также не должны быть в вашем JSON.
Если вы не можете исправить, где вы получили эту строку JSON для создания допустимого JSON, вы можете либо удалить оскорбительные символы:
>>> json.loads(s.replace('\r\n', ''))
или выполните их вручную:
>>> json.loads(s.replace('\r\n', '\\r\\n'))
Ответ 2
Другим вариантом, возможно, является использование аргумента strict=False
Согласно http://docs.python.org/2/library/json.html
"Если strict - False (True - значение по умолчанию), тогда управляющие символы будут разрешены внутри строк. Управляющими символами в этом контексте являются символы с кодами символов в диапазоне 0-31, включая '\ t' (tab) '\n', '\ r' и '\ 0'."
Например:
json.loads(json_str, strict=False)
Ответ 3
Проблема заключается в том, что символ в индексе 33 является символом управления возвратом каретки.
>>> s[33]
u'\r'
В соответствии с спецификацией JSON действительными символами являются:
-
Любой символ Юникода, кроме: "
, \
и управляющих символов (ord(char) < 32
).
-
Разрешены следующие последовательности символов: \"
, \\
, \/
, \b
(backspace), \f
(form feed), \n
(line-feed/new- line), \r
(возврат каретки), \t
(tab) или \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'}
Литература:
Ответ 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'}
Ответ 5
В некоторых случаях эта ошибка возникает, когда файл фактически содержит строку с пробелом в ней. Удаление пробела решит проблему.