前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >半小时掌握Python的JSON模块

半小时掌握Python的JSON模块

作者头像
疯狂软件李刚
发布2020-06-24 11:31:58
8570
发布2020-06-24 11:31:58
举报
文章被收录于专栏:疯狂软件李刚疯狂软件李刚

导读

本文详细介绍了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__命令,即可看到该模块所包含的全部属性和函数。

代码语言:javascript
复制
>>> json.__all__
['dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder']

json模块中常用的函数和类的功能如下。

  • json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan= True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw):将obj对象转换成JSON字符串输出到fp流中,fp是一个支持write()方法的类文件对象。
  • json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan= True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw):将obj对象转换为JSON字符串,并返回该JSON字符串。
  • json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_ constant=None, object_pairs_hook=None, **kw):从fp流读取JSON字符串,将其恢复成JSON对象,其中fp是一个支持write()方法的类文件对象。
  • json.loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_ int=None, parse_constant=None, object_pairs_hook=None, **kw):将JSON字符串s恢复成JSON对象。

通过上面4个功能函数就可以实现JSON的两个主要应用场景,由于JSON只是一种轻量级的数据交换格式,因此JSON的主要应用场景如图1所示。

图1 Python的JSON支持

下面程序示范了dumps()和dump()函数的encode操作(将Python对象转换成JSON字符串)。

代码语言:javascript
复制
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字符串输出到文件中。

运行上面程序,可以看到如下输出结果。

代码语言:javascript
复制
["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对象)。

代码语言:javascript
复制
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列表。运行上面程序,可以看到如下输出结果。

代码语言:javascript
复制
['yeeku', {'favorite': ['coding', None, 'game', 25]}]
"foo"bar
(1+2j)
['Kotlin', {'Python': 'excellent'}]

此外,我们还需要考虑一个问题:Python支持更多的JSON所不支持的类型,比如复数、矩阵等,如果直接使用dumps()或dump()函数进行转换,程序肯定会出问题。此时就需要开发者对JSONEncoder类进行扩展,通过这种扩展来完成从Python特殊类型到JSON类型的转换。

例如,如下程序示范了通过扩展JSONEncoder来实现从Python复数到JSON字符串的转换。

代码语言:javascript
复制
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的子类之后,程序有两种方式来使用自定义的子类。

  • 在dumps()或dump()函数中通过cls属性指定使用JSONEncoder的自定义子类。
  • 直接使用JSONEncoder的自定义子类的encode()方法来执行转换。

运行该程序,可以看到如下输出结果。

代码语言:javascript
复制
{"__complex__": "true", "real": 2.0, "imag": 1.0}
{"__complex__": "true", "real": 2.0, "imag": 1.0}

本文结束

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 疯狂软件李刚 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档