使用Python将JSON字符串转换为字典

485

我在Python中对JSON感到有些困惑。在我看来,它似乎像个字典,因此我正在尝试这样做:

{
    "glossary":
    {
        "title": "example glossary",
        "GlossDiv":
        {
            "title": "S",
            "GlossList":
            {
                "GlossEntry":
                {
                    "ID": "SGML",
                    "SortAs": "SGML",
                    "GlossTerm": "Standard Generalized Markup Language",
                    "Acronym": "SGML",
                    "Abbrev": "ISO 8879:1986",
                    "GlossDef":
                    {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
                        "GlossSeeAlso": ["GML", "XML"]
                    },
                    "GlossSee": "markup"
                }
            }
        }
    }
}

但是当我执行print(dict(json))时,会出现错误。

我该如何将这个字符串转换为一个结构,并调用json["title"]来获取"example glossary"

4个回答

849

json.loads()

import json

d = json.loads(j)
print d['glossary']['title']

11
json.load是用于从文件中加载JSON数据的函数,而json.loads则是用于从字符串中加载JSON数据的函数。两者的区别在于它们所接受的输入类型不同。 - Shivam Agrawal
6
@ShivamAgrawal的意思是,“正好就像罐头上写的一样” [on the tin],指的是链接中文档所述的内容。 - Ignacio Vazquez-Abrams
81
.load().loads() 的区别在于,.load() 解析文件对象,而 .loads() 解析字符串 / Unicode 对象。 - fyngyrz
3
我感到困扰的是这个函数的作者没有编写一个包装函数来对传入的数据进行类型检查,并自动选择正确的函数调用。我也不喜欢使用的模糊命名方式。以下是我为了解决这个问题所编写的内容:def read_json(json_data): if isinstance(json_data, str): return json.loads(json_data) elif hasattr(json_data, 'read'): return json.load(json_data)我相信这可以得到改进,但现在你可以在一个json字符串或文件上调用 d = read_json(j) - Jacques Mathieu
2
@JacquesMathieu,你好Jacques,感谢你的函数,我做了一些小改进,因为有时我使用字典:def read_json(json_data): if (type(json_data) == str): # 对于字符串 return json.loads(json_data) elif (str(type(json_data)) == "<class '_io.TextIOWrapper'>"): #对于文件 return json.load(json_data) elif (type(json_data) == dict): # 对于字典 return json.loads(json.dumps(json_data)) - Gabriel Aizcorbe
1
你们为什么要使用这种奇怪的字符串比较方式,而不是像 isinstance(json_data, io.TextIOBase) 这样的方式呢?有很多类型的行为类似于文件,我猜捕获这些类型也会很有用。 - Christian

118

当我开始使用json时,我感到困惑并且无法在一段时间内弄清楚,但最终我得到了我想要的结果
这里是简单的解决方案

import json
m = {'id': 2, 'name': 'hussain'}
n = json.dumps(m)
o = json.loads(n)
print(o['id'], o['name'])

你为什么要先转储(dumps) m? - Han Van Pham
我使用它来演示序列化和反序列化。使用loads(..)处理'{"id": 2, "name": "hussain"}'也可以像接受的答案一样良好。 - Hussain
1
转换和加载对我来说完美无缺,而被接受的答案则不是。非常感谢@Hussain为我节省了时间。顺便提一下,我正在尝试从具有UTF-8编码的动态字符串中进行加载... - Mohammed Sufian

25

如果您信任数据源,可以使用 eval 来将字符串转换为字典:

eval(your_json_format_string)

示例:

>>> x = "{'a' : 1, 'b' : True, 'c' : 'C'}"
>>> y = eval(x)

>>> print x
{'a' : 1, 'b' : True, 'c' : 'C'}
>>> print y
{'a': 1, 'c': 'C', 'b': True}

>>> print type(x), type(y)
<type 'str'> <type 'dict'>

>>> print y['a'], type(y['a'])
1 <type 'int'>

>>> print y['a'], type(y['b'])
1 <type 'bool'>

>>> print y['a'], type(y['c'])
1 <type 'str'>

1
你的示例字符串不是JSON。 - bfontaine
1
True。它评估为一个字典,可以轻松地加载/转储为JSON(当然,如果您的字典具有非JSON值,则可能需要自定义JSON编码器函数)。 - kakhkAtion
6
不。你绝不能将输入数据作为代码进行评估。这可能是你个人的小项目,使用你信任的数据,但糟糕的代码可能会在实际项目中被重复使用,不良做法会留下安全隐患。 - NetworkMeister
1
这就是为什么我的答案以“如果您信任数据源”的条件开始!但是确实,这更像是一种hack,绝对不是最佳实践。 - kakhkAtion
2
如果数据源是你自己的话,你完全可以信任它。这实际上非常有用,可以将一个字符串化的JS对象转换为一个字典,再转换为正确的JSON字符串。 - Vadorequest
@NetworkMeister 有时候,如果字符串是硬编码/自行生成的/为自己的需求初始化,那么eval并不是邪恶的。此外,没有人可以操纵数据。 - poring91

22

使用 simplejson 或 cjson 来提升速度。

import simplejson as json

json.loads(obj)

or 

cjson.decode(obj)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接