导读
本文详细介绍了Python json模块的用法,本文适合Python GUI编程的小白上手。
json模块提供了对JSON的支持,它既包含了将JSON字符串恢复成Python对象的函数,也提供了将Python对象转换成JSON字符串的函数。
当程序把JSON对象或JSON字符串转换成Python对象时,从JSON类型到Python类型的转换关系如表1所示。
表1 JSON类型转换Python类型的对应关系
JSON类型 | Python类型 |
---|---|
对象(object) | 字典(dict) |
数组(array) | 列表(list) |
字符串(string) | 字符串(str) |
整数(number(int)) | 整数(int) |
实数(number(real)) | 浮点数(float) |
true | True |
false | False |
null | None |
当程序把Python对象转换成JSON格式字符串时,从Python类型到JSON类型的转换关系如表2所示。
表2 Python类型转换JSON类型的对应关系
Python类型 | JSON类型 |
---|---|
字典(dict) | 对象(object) |
列表(list)和元组(tuple) | 数组(array) |
字符串(str) | 字符串(string) |
整型、浮点型,以及整型、浮点型派生的枚举(float, int- & float-derived Enums) | 数值型(number) |
True | true |
False | false |
None | null |
在Python的交互式解释器中先导入json模块,然后输入json.__all__命令,即可看到该模块所包含的全部属性和函数。
>>> json.__all__
['dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder']
json模块中常用的函数和类的功能如下。
通过上面4个功能函数就可以实现JSON的两个主要应用场景,由于JSON只是一种轻量级的数据交换格式,因此JSON的主要应用场景如图1所示。
图1 Python的JSON支持
下面程序示范了dumps()和dump()函数的encode操作(将Python对象转换成JSON字符串)。
import json
# 将Python对象转换为JSON字符串(元组会被当成数组)
s = json.dumps(['yeeku', {'favorite': ('coding', None, 'game', 25)}])
print(s) # ["yeeku", {"favorite": ["coding", null, "game", 25]}]
# 将简单的Python字符串转换为JSON字符串
s2 = json.dumps("\"foo\bar")
print(s2) #"\"foo\bar"
# 将简单的Python字符串转换为JSON字符串
s3 = json.dumps('\\')
print(s3) #"\\"
# 将Python的dict对象转换为JSON字符串,并对key排序
s4 = json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
print(s4) #{"a": 0, "b": 0, "c": 0}
# 将Python列表转换为JSON字符串
# 并指定JSON分隔符:在逗号和冒号之后没有空格(默认有空格)
s5 = json.dumps([1, 2, 3, {'x': 5, 'y': 7}], separators=(',', ':'))
# 在输出的JSON字符串中,在逗号和冒号之后没有空格
print(s5) # '[1,2,3,{"4":5,"6":7}]'
# 指定indent为4,意味着转换的JSON字符串有缩进
s6 = json.dumps({'Python': 5, 'Kotlin': 7}, sort_keys=True, indent=4)
print(s6)
# 使用JSONEncoder的encode方法将Python对象转换为JSON字符串
s7 = json.JSONEncoder().encode({"names": ("孙悟空", "齐天大圣")})
print(s7) # {"names": ["\u5b59\u609f\u7a7a", "\u9f50\u5929\u5927\u5723"]}
f = open('a.json', 'w')
# 使用dump()函数将转换得到的JSON字符串输出到文件中
json.dump(['Kotlin', {'Python': 'excellent'}], f)
上面程序主要是调用dumps()函数执行encode操作,程序在调用dumps()函数时指定了不同的选项。上面程序最后一行代码调用dump()函数将通过encode操作得到的JSON字符串输出到文件中。实际上,dumps()和dump()函数的功能、所支持的选项基本相同,只是dumps()函数直接返回转换得到的JSON字符串,而dump()函数则将转换得到的JSON字符串输出到文件中。
运行上面程序,可以看到如下输出结果。
["yeeku", {"favorite": ["coding", null, "game", 25]}]
"\"foo\bar"
"\\"
{"a": 0, "b": 0, "c": 0}
[1,2,3,{"x":5,"y":7}]
{
"Kotlin": 7,
"Python": 5
}
{"names": ["\u5b59\u609f\u7a7a", "\u9f50\u5929\u5927\u5723"]}
程序运行结束后,会在程序所在目录生成一个a.json文件,该文件内容就是转换得到的JSON字符串。
正如从上面程序中代码所看到的,程序调用json.JSONEncoder对象的encode()方法也可以将Python对象转换为JSON字符串。而dumps()和dump()函数是更高级的调用方式,一般调用dumps()和dump()函数对Python对象执行转换即可。
下面程序示范了loads()和load()函数的decode操作(将JSON字符串转换成Python对象)。
import json
# 将JSON字符串恢复成Python列表
result1 = json.loads('["yeeku", {"favorite": ["coding", null, "game", 25]}]')
print(result1) # ['yeeku', {'favorite': ['coding', None, 'game', 25]}]
# 将JSON字符串恢复成Python字符串
result2 = json.loads('"\\"foo\\"bar"')
print(result2) # "foo"bar
# 定义一个自定义的转换函数
def as_complex(dct):
if '__complex__' in dct:
return complex(dct['real'], dct['imag'])
return dct
# 使用自定义的恢复函数
# 自定义的恢复函数将real数据转换成复数的实部,将imag转换成复数的虚部
result3 = json.loads('{"__complex__": true, "real": 1, "imag": 2}',\
object_hook=as_complex)
print(result3) # (1+2j)
f = open('a.json')
# 从文件流恢复JSON列表
result4 = json.load(f)
print(result4) # ['Kotlin', {'Python': 'excellent'}]
上面程序开始调用loads()函数从JSON字符串恢复Python列表、Python字符串等。接下来程序示范了一个比较特殊的例子—程序定义了一个自定义的恢复函数,该函数负责将一个原本应该恢复成dict对象的JSON字符串恢复成复数,并负责将字典中real对应的值转换成复数的实部,将字典中imag对应的值转换成复数的虚部。
通过使用自定义的恢复函数,可以完成JSON类型到Python特殊类型(如复数、矩阵)的转换。
上面程序最后使用load()函数示范了从文件流来恢复JSON列表。运行上面程序,可以看到如下输出结果。
['yeeku', {'favorite': ['coding', None, 'game', 25]}]
"foo"bar
(1+2j)
['Kotlin', {'Python': 'excellent'}]
此外,我们还需要考虑一个问题:Python支持更多的JSON所不支持的类型,比如复数、矩阵等,如果直接使用dumps()或dump()函数进行转换,程序肯定会出问题。此时就需要开发者对JSONEncoder类进行扩展,通过这种扩展来完成从Python特殊类型到JSON类型的转换。
例如,如下程序示范了通过扩展JSONEncoder来实现从Python复数到JSON字符串的转换。
import json
# 定义JSONEncoder的子类
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
# 如果要转换的对象是复数类型,程序负责处理
if isinstance(obj, complex):
return {"__complex__": 'true', 'real': obj.real, 'imag': obj.imag}
# 对于其他类型,还使用JSONEncoder默认处理
return json.JSONEncoder.default(self, obj)
s1 = json.dumps(2 + 1j, cls=ComplexEncoder)
print(s1) # '{"__complex__": "true", "real": 2.0, "imag": 1.0}'
s2 = ComplexEncoder().encode(2 + 1j)
print(s2) # '{"__complex__": "true", "real": 2.0, "imag": 1.0}'
上面程序扩展了JSONEncoder类的子类,并重写了它的default()方法,在方法中判断如果要转换的目标类型是复数(complex),程序就会进行自定义转换—将复数转换成JSON对象,且该对象包含"__complex__": 'true'属性。
一旦扩展了JSONEncoder的子类之后,程序有两种方式来使用自定义的子类。
运行该程序,可以看到如下输出结果。
{"__complex__": "true", "real": 2.0, "imag": 1.0}
{"__complex__": "true", "real": 2.0, "imag": 1.0}
本文结束