3

我有一个非常简单的 json,我无法用 simplejson 模块解析。再生产:

import simplejson as json
json.loads(r'{"translatedatt1":"Vari\351es"}')

结果:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.5/simplejson/__init__.py", line 307, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/pymodules/python2.5/simplejson/decoder.py", line 335, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/pymodules/python2.5/simplejson/decoder.py", line 351, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Invalid \escape: line 1 column 23 (char 23)

任何人都知道出了什么问题以及如何正确解析上面的json?

在那里编码的字符串是:Variées

PS我使用python 2.5

非常感谢!

4

2 回答 2

8

那是完全正确的;Vari\351es包含无效转义,JSON 标准不允许 a\后跟数字。

无论产生什么代码都应该被修复。如果这是不可能的,您将需要使用正则表达式来删除这些转义,或者用有效的转义替换它们。

如果我们将该351数字解释为八进制数字,那将指向 unicode 代码点 U+00E9,即é字符(带有 ACUTE 的拉丁小写字母 E)。您可以使用以下方法“修复”您的 JSON 输入:

import re

invalid_escape = re.compile(r'\\[0-7]{1,6}')  # up to 6 digits for codepoints up to FFFF

def replace_with_codepoint(match):
    return unichr(int(match.group(0)[1:], 8))


def repair(brokenjson):
    return invalid_escape.sub(replace_with_codepoint, brokenjson)

使用repair()您的示例可以加载:

>>> json.loads(repair(r'{"translatedatt1":"Vari\351es"}'))
{u'translatedatt1': u'Vari\xe9es'}

您可能需要调整代码点的解释;我选择八进制(因为Variées是一个实际的单词),但您需要使用其他代码点进行更多测试。

于 2013-02-03T15:34:20.520 回答
4

您可能不打算使用原始字符串,而是使用 unicode 字符串?

>>> import simplejson as json
>>> json.loads(u'{"translatedatt1":"Vari\351es"}')
{u'translatedatt1': u'Vari\xe9es'}

如果要引用 JSON 字符串中的数据,则需要使用\uNNNN

>>> json.loads(r'{"translatedatt1":"Vari\u351es"}')
{'translatedatt1': u'Vari\u351es'}

请注意,在这种情况下,生成的 dict 略有不同。解析 unicode 字符串时 simplejsonunicode strings用于键。否则它使用byte string密钥。

如果您的 JSON 数据确实使用\351e,那么它只是被破坏并且没有有效的 JSON。

于 2013-02-03T15:34:05.417 回答