【问题标题】:Can't parse simple json with python无法用python解析简单的json
【发布时间】:2013-02-03 15:29:28
【问题描述】:

我有一个非常简单的 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

附:我使用 python 2.5

非常感谢!

【问题讨论】:

    标签: python json simplejson


    【解决方案1】:

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

    应该修复生成该代码的任何内容。如果这是不可能的,您需要使用正则表达式来删除这些转义,或者用有效的转义替换它们。

    如果我们将351 数字解释为八进制数字,那将指向 unicode 代码点 U+00E9,é 字符(带有锐音的拉丁小写字母 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 是一个实际单词),但您需要使用其他代码点进行更多测试。

    【讨论】:

    • 此代码是为/由文达平台生成的。不幸的是,我无法改变这种行为。顺便说一句 - 什么是有效的逃逸者?
    • 谢谢,但结果不是应该的:在 rapair 函数之后,我们得到“Varişes”,而它应该是“Variées”
    • @diemacht:已更新 :-) 由于您没有指定您的预期,我不得不猜测,然后更新我的猜测。
    【解决方案2】:

    您可能不打算使用原始字符串,而是使用 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 字符串时,simplejson 使用 unicode strings 作为键。否则它使用byte string 键。

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

    【讨论】:

    • 如果字符串在某个变量中,我可以这样做吗,例如: s=r'{"translatedatt1":"Vari\351es"}' ?谢谢!!!
    • 只是不要那样创建字符串。如果要创建包含 unicode 数据的字符串,请去掉 r 前缀并改用 u。如果你真的想在 JSON 数据中使用引用,你需要使用 \u351e
    • @bikeshedder:我认为 OP 意味着 服务器 发送了该数据。 r'' 可以更轻松地向我们展示发送的原始数据。是的,这是损坏的 JSON 数据...
    • U+351E 是 CJK 表意文字扩展 A.. 也不确定这是正确的解释。我认为你更接近八进制..
    猜你喜欢
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多