JSON(JavaScript Object Notation)是一种使用JavaScript表示的轻量级数据格式。JSON数据包很小并且很快被浏览器解析。今天我们将探讨如何在Python中读取和编写JSON数据。

有这么一组数据:

注意:最后一行的Sławomir Idziak,其中Sławomir中的ł是带有横线的拉丁文小写字母L,它不是一个 ASCII 字符,你可以在 Python 中用print(u'\u0142')将其打印出来。

你可以查看:https://www.fileformat.info/info/unicode/char/0142/index.htm ,这里使用它是为了说明 JSON 编码的区别。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
    "title": "Gattaca",
    "release_year": 1997,
    "is_awesome": true,
    "won_oscar": false,
    "actors": ["Ethan Hawke", "Uma Thurman", "Alan Arkin",
               "Loren Dean"],
    "budget": null,
    "credits": {
        "director": "Andrew Niccol",
        "writer": "Andrew Niccol",
        "composer": "Michael Nyman",
        "cinematogtapher": "Sławomir Idziak"
    }
}

它看起来就像是 Python 中的字典,但也有一些例外。Python 中的TrueFalse是以大写字母开头,而在 JSON 中却是小写。

它所有的键(key)都是字符串,而值(value)可以是字符串、数字、布尔值、列表、null,甚至是另一个 JSON 对象。

首先,将上面的JSON数据以utf-8 无BOM格式编码的格式保存在movie_1.txt文件中,然后我们接下来看一下对 JSON 数据进行编码或者解码的函数方法。如下所示:

1
2
3
import json

print(dir(json))

输出结果如下:

1
['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner']

我们这里主要关注dumpdumpsloadloads这四个方法。

  • json.load(f):用于从文件中加载JSON数据
  • json.loads(s):用于从字符串中加载JSON数据
  • json.dump(j, f):用于将JSON对象写入文件
  • json.dupms(j):用于将JSON对象输出为字符串

1. json.load

json.load(f):用于从文件中加载 JSON 数据

键入如下代码:

1
2
3
4
5
6
7
8
import json

json_file = open("f:/Python_test/BasicKnowledge/movie_1.txt", 'r', encoding='utf-8')
moive = json.load(json_file)
json_file.close()

print(moive)
print(type(moive))

输出结果如下:

1
2
{'title': 'Gattaca', 'release_year': 1997, 'is_awesome': True, 'won_oscar': False, 'actors': ['Ethan Hawke', 'Uma Thurman', 'Alan Arkin', 'Loren Dean'], 'budget': None, 'credits': {'director': 'Andrew Niccol', 'writer': 'Andrew Niccol', 'composer': 'Michael Nyman', 'cinematogtapher': 'Sławomir Idziak'}}
<class 'dict'>

你可以看到,movie事实上是一个字典类型。同时注意到truefalsenull都变成了Python中的TrueFalseNone,并且正确解析了非 ASCII 字符ł

由于这是一个字典,你可以通过key来访问数据。如下所示:

1
2
3
print(moive['title'])
print(moive['actors'])
print(moive['release_year'])

输出结果如下:

1
2
3
Gattaca
['Ethan Hawke', 'Uma Thurman', 'Alan Arkin', 'Loren Dean']
1997

2. json.loads

json.loads(s):用于从字符串中加载 JSON 数据

键入如下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import json
value = """
    {"title": "Tron: Legacy",
    "composer": "Daft Puck",
    "release_year" : 2010,
    "budget": 170000000,
    "actors": null,
    "won_oscar": false
    }"""

tron = json.loads(value)
print(tron)

输出结果如下:

1
{'title': 'Tron: Legacy', 'composer': 'Daft Puck', 'release_year': 2010, 'budget': 170000000, 'actors': None, 'won_oscar': False}

首先创建了一个带有 JSON 格式值的字符串。要解析这个 JSON 数据,可以通过调用loads函数来实现。因为所有字符都是 ASCII,所以不需要担心编码问题。

查看结果你会发现,它生成了一个 Python 字典,所有数据都进行了正确的转换。False是 Python 中的布尔类型,null被转换为None

3. json.dumps

json.dupms(j):用于将 JSON 对象输出为字符串

如果要将字典转换为有效的JSON字符串,可以在使用dumps方法时传入字典。如下所示:

1
2
3
4
5
6
7
8
import json

json_file = open("f:/Python_test/BasicKnowledge/movie_1.txt", 'r', encoding='utf-8')
moive = json.load(json_file)
json_file.close()

print(moive)
print(json.dumps(moive))

输出结果如下:

1
2
{'title': 'Gattaca', 'release_year': 1997, 'is_awesome': True, 'won_oscar': False, 'actors': ['Ethan Hawke', 'Uma Thurman', 'Alan Arkin', 'Loren Dean'], 'budget': None, 'credits': {'director': 'Andrew Niccol', 'writer': 'Andrew Niccol', 'composer': 'Michael Nyman', 'cinematogtapher': 'Sławomir Idziak'}}
{"title": "Gattaca", "release_year": 1997, "is_awesome": true, "won_oscar": false, "actors": ["Ethan Hawke", "Uma Thurman", "Alan Arkin", "Loren Dean"], "budget": null, "credits": {"director": "Andrew Niccol", "writer": "Andrew Niccol", "composer": "Michael Nyman", "cinematogtapher": "S\u0142awomir Idziak"}}

结果看到返回了一个正确的 JSON 格式字符串,truefalse都被转换成了小写。但是注意:非 ASCII 字符ł不会原格式输出。因为JSON库默认输出为 ASCII 字符,并且将转义所有非 ASCII 字符。

如果要避免这种情况发生,让其输出原格式的ł,可以在使用dumps方法时,指定ensure_ascii=False即可。如下所示:

1
print(json.dumps(moive, ensure_ascii=False))

输出结果如下:

1
{"title": "Gattaca", "release_year": 1997, "is_awesome": true, "won_oscar": false, "actors": ["Ethan Hawke", "Uma Thurman", "Alan Arkin", "Loren Dean"], "budget": null, "credits": {"director": "Andrew Niccol", "writer": "Andrew Niccol", "composer": "Michael Nyman", "cinematogtapher": "Sławomir Idziak"}}

现在结果保留了非 ASCII 字符,并且不反转反斜杠。

4. json.dump

json.dump(j, f):用于将 JSON 对象写入文件

现在我们创建一个新对象,将其转换为 JSON,并写入文件。

首先创建一个movie2字典,并初始化字典中的数据。注意在cinematographer中的值中有一个 Unicode 编码。这个编码最后会被解析成带有一撇的拉丁文小写字母 N,就是 ń

创建好以后使用utf-8编码以写入模式打开文件,然后调用dump方法。因为我们的数据中含有非 ASCII 字符,所以将ensure_ascii设置为False,最后关闭文件即可。如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import json

moive2 = {}
moive2['title'] = 'Minority Report'
moive2['director'] = 'Steven Spielberg'
moive2['composer'] = 'John Williams'
moive2['actors'] = ['Tom Cruise', 'Colin Farrell',
                    'Samantha Morton', 'Max von Sydow']
moive2['is_awesom'] = True
moive2['budget'] = 102000000
moive2['cinematographer'] = 'Janusz Kami\u0144ski'  # 注意这里的Unicode编码

file2 = open('f:/Python_test/BasicKnowledge/movie_2.txt', 'w', encoding='utf-8')
json.dump(moive2, file2, ensure_ascii=False)
file2.close()

点击movies_2.txt文件后,你可以看见JSON格式的数据。如下图:

JSON

之后我们就可以用这种格式进行文件的传输,也可以利用JSON对数据进行解析,便于分类。