【问题标题】:Why does json.loads care which type of quotes are used?为什么 json.loads 关心使用哪种类型的引号?
【发布时间】:2015-04-12 10:39:08
【问题描述】:

在 python 脚本中,我正在解析返回的
gsettings get org.gnome.system.proxy ignore-hosts
看起来应该正确格式化JSON
['localhost', '127.0.0.0/8']
但是,当将此输出传递给 json.loads 时,它会抛出
ValueError: No JSON object could be decoded

我通过以下方式调用 gsettings:

import subprocess
proc = subprocess.Popen(["gsettings", "get", "org.gnome.system.proxy", "ignore-hosts"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)  
stdout,stderr = proc.communicate()

"['localhost', '127.0.0.0/8']\n" 分配给stdout。 然后我去掉换行符并传递给 json.loads:

ignore = json.loads(stdout.strip("\n"))

但是,这会引发ValueError

我已将问题追溯到由单引号或双引号定义的字符串,如下面的 sn-p 所示:

# tested in python 2.7.3

import json

ignore_hosts_works = '["localhost", "127.0.0.0/8"]'
ignore_hosts_fails = "['localhost', '127.0.0.0/8']"

json.loads(ignore_hosts_works) # produces list of unicode strings
json.loads(ignore_hosts_fails) # ValueError: No JSON object could be decoded

import string
table = string.maketrans("\"'", "'\"")

json.loads(string.translate(ignore_hosts_fails, table)) # produces list of unicode strings

为什么json.loads 没有在不交换引号类型的情况下成功解析ignore_hosts_fails

以防万一,我正在运行带有 Python 2.7.3 的 Ubuntu 12.04。

【问题讨论】:

  • ['localhost', '127.0.0.0/8'] 的 JSON 格式不正确。 JSON 要求使用 引号。见chapter 7 of the RFCquotation-mark定义为"
  • 啊,谢谢。 双引号要求在阅读json.org时对我来说并不突出。

标签: python json string python-2.7


【解决方案1】:

因为RFC 7159 这么说。 JSON 文档中的字符串用双引号括起来。

【讨论】:

    【解决方案2】:

    JSON 不仅仅是 JavaScript。

    根据规范pdfjson.org,JSON 字符串是双引号。

    JSON 对象键是字符串。

    必须为您的字符串和键使用双引号(以遵循规范)。许多 JSON 解析器会更加宽松。

    来自object 定义:

    对象结构表示为一对围绕零个或多个名称/值对的花括号标记。

    名称是一个字符串。每个名称后面都有一个冒号标记,将名称与值分开。单个逗号标记将值与后面的名称分开。

    来自string 定义:

    字符串是用引号 (U+0022) 包裹的 Unicode 代码点序列。

    U+0022 是(双)引号:"

    【讨论】:

      【解决方案3】:

      来自JSON RFC 7159

        string = quotation-mark *char quotation-mark
      

      [...]

        quotation-mark = %x22      ; "
      

      JSON 字符串必须使用" 引号。

      您可以使用 ast.literal_eval() 将该列表解析为 Python 文字:

      >>> import ast
      >>> ast.literal_eval("['localhost', '127.0.0.0/8']")
      ['localhost', '127.0.0.0/8']
      

      【讨论】:

        【解决方案4】:

        如前所述,这是无效的 JSON。要解析,还有另外两种可能:使用demjsonyaml

        >>> demjson.decode(" ['localhost', '127.0.0.0/8']")
        [u'localhost', u'127.0.0.0/8']
        >>> yaml.load(" ['localhost', '127.0.0.0/8']")
        ['localhost', '127.0.0.0/8']
        

        【讨论】:

          【解决方案5】:

          是的,它关心有效的 json。但是您可以调整简单的 json 代码来解析这个不带引号和单引号的 json 字符串。

          我已经在这篇文章中给出了答案

          Single versus double quotes in json loads in Python

          【讨论】:

            猜你喜欢
            • 2019-08-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-07
            • 2022-11-02
            • 1970-01-01
            • 2010-09-13
            相关资源
            最近更新 更多