1、概述
json数据格式也是比较常用数据传输格式,各类编程语言都有对JSON字符串与对象的各种转换,JSON数据转化在java中经常用到,在java中有自带JSONObject类来进行处理。在Python3中提供了json模块来进行处理。使用json模块之前先导入它:
import json
2、常用函数
函数名 | 描述 |
---|---|
json.dump(obj,fp) | 使用这个 转换表 将 obj 序列化为 JSON 格式化流形式的 fp (支持 .write() 的 file-like object)。即:将对象转换成文件流的形式 |
json.dumps(obj) | 使用这个 转换表 将 obj 序列化为 JSON 格式的 str。 其参数的含义与 dump() 中的相同。即:将对象转换成JSON字符串 |
json.load(fp) | 使用这个 转换表 将 fp (一个支持 .read() 并包含一个 JSON 文档的 text file 或者 binary file) 反序列化为一个 Python 对象。即:将文件流转换成对象 |
json.loads(s) | 使用这个 转换表 将 s (一个包含 JSON 文档的 str, bytes 或 bytearray 实例) 反序列化为 Python 对象。即:将JSON字符串转换成对象 |
decode(s) | 返回 s 的 Python 表示形式(包含一个 JSON 文档的 str 实例)。如果给定的 JSON 文档无效则将引发 JSONDecodeError。 |
encode(o) | 返回 Python o 数据结构的 JSON 字符串表达方式。 |
在上表中常用函数的参数只列出了必填参数,而一些缺省参数没有列出来。
json.loads函数完整格式:
json.loads(s, *, cls=None, object_hook=None, parse_float=None,
parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
参数说明:
json.dumps函数完整格式
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)
参数说明
3、应用场景
3.1、字典与JSON对象互转
举个例子:
import json
# 创建一个字典
dic = {'name': '小明', 'age': 18}
print("转之前的字典:", dic)
# 如果 ensure_ascii 是 true (即默认值),输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false,这些字符会原样输出。
# 字典转换成json对象
jsonObj = json.dumps(dic,ensure_ascii=False)
print("JSON对象:", jsonObj)
# json对象转换成字典
redic = json.loads(jsonObj)
print("转之后的字典:", jsonObj)
注意上述代码中用到 了ensure_ascii = False这个标记参数。
如果 ensure_ascii 是 true (即默认值),输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false,这些字符会原样输出。
输出:
转之前的字典: {'name': '小明', 'age': 18}
JSON对象: {"name": "小明", "age": 18}
转之后的字典: {"name": "小明", "age": 18}
3.2、列表与JSON对象互转
直接使用
list=[1,2,3,4]
这种结构是不能直接转换成JSON对象的,但是有另外一种结构即list中包含字典,如:
list=[{"id": "1", "title": "测试标题1", "subTitle": "子标题1"},{"id": "2", "title": "测试标题2", "subTitle": "子标题2"}]
这种结构是能转换成json对象的。
举个例子:
import json
# 创建一个字典
dic = {'name': '小明', 'age': 18}
dic2 = {'name': '小花', 'age': 16}
print("转之前的字典:", dic)
print("转之前的字典:", dic2)
list=[]
list.append(dic)
list.append(dic2)
print("转之前的列表:",list)
# 如果 ensure_ascii 是 true (即默认值),输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false,这些字符会原样输出。
# 列表转换成json对象
jsonObj = json.dumps(list,ensure_ascii=False)
print("JSON对象:", jsonObj)
# json对象转换成列表
reList = json.loads(jsonObj)
print("转之后的列表:", jsonObj)
输出:
转之前的字典: {'name': '小明', 'age': 18}
转之前的字典: {'name': '小花', 'age': 16}
转之前的列表: [{'name': '小明', 'age': 18}, {'name': '小花', 'age': 16}]
JSON对象: [{"name": "小明", "age": 18}, {"name": "小花", "age": 16}]
转之后的列表: [{"name": "小明", "age": 18}, {"name": "小花", "age": 16}]
3.3、class类与JSON对象互转
class类转JSON对象或者字符串转JSON对象再转类对象这些都是在实际项目开发中频繁使用的。所以下面的例子做了这些实践。当然还有一些更多的办法,大家可以自行扩展。
举个例子:
import json
# 声明一个类
class Student:
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
@property
def age(self):
return self.__age
@age.setter
def age(self, age):
self.__age = age
# 定义一个独立的接收方法 通过 object_hook 调用
def handle(dic):
s = Student()
s.name = dic['_Student__name']
s.age = dic['_Student__age']
return s
std = Student()
std.name = "小明"
std.age = 18
print("原对象:", std)
# 将class类转成json对象 ,在转换之前需要先序列化类(类实例.__dict__可序列化类),不序列化会报错 TypeError: Object of type 'Student' is not JSON serializable
jsonObj = json.dumps(std.__dict__, ensure_ascii=False)
print("JSON对象:", jsonObj)
# encode & decode 用法
encodeStr = json.JSONEncoder().encode(jsonObj)
print("JSON对象转换成JSON字符串:", encodeStr)
decodeStr = json.JSONDecoder().decode(encodeStr)
print("JSON字符串转换成JSON对象:", decodeStr)
# 将json对象转化成类对象
std2 = json.loads(jsonObj, object_hook=handle)
print("std2是否属于Student类的实例:", isinstance(std2, Student))
# 输出类对象的属性值
print(std2.name, std2.age)
# 往当前目录下的data.json 这个文件 写入 std2 类对象的数据,如果没有这个文件会自动创建
with open('data.json', 'w', encoding="utf-8") as f:
json.dump(std2.__dict__, f, ensure_ascii=False)
# 用with open 语句 f.flush() 与 f.close()语句可以不用写了
# 读取data.json文件内容
with open('data.json', 'r', encoding="utf-8") as f:
data = json.load(f)
print("从data.json文件中读取json字符串,并转化为JSON对象:", data)
温馨提示:
- 类对象转JSON对象时,需要先序列化类,可通过[类实例.dict]的方式进行序列化,若不序列化类,则会报错TypeError:
Object of type ‘Student’ is not JSON serializable。 - JSON对象转换成Python对象后返回的其实是一个字典类型,我们需要将字典的键值设置到对应的类对象的属性上,然后再返回这个类对象,就可以直接使用了。
输出:
原对象: <__main__.Student object at 0x0000023F75D74898>
JSON对象: {"_Student__name": "小明", "_Student__age": 18}
JSON对象转换成JSON字符串: "{\"_Student__name\": \"\u5c0f\u660e\", \"_Student__age\": 18}"
JSON字符串转换成JSON对象: {"_Student__name": "小明", "_Student__age": 18}
std2是否属于Student类的实例: True
小明 18
从data.json文件中读取json字符串,并转化为JSON对象: {'_Student__name': '小明', '_Student__age': 18}
4、总结
关于 json.JSONEncoder().encode(jsonObj)函数的直白理解:JSON对象转换成JSON字符串;
关于 json.JSONDecoder().decode(encodeStr)函数的直白理解:JSON字符串转换成JSON对象;
关于json.dump&json.load两个不带s的函数这里非常有用,可以想象的是做一些缓存操作,预先把缓存json数据存储到本地文件中,然后再读取出来使用,特别注意的是使用中文的时候要记得设置编码为utf-8;
注意本文使用了==with open ==语句 ,所以 f.flush() 与 f.close()语句可以不用写了,原因是:
If a file descriptor is given, it is closed when the returned I/O object is closed, unless closefd is set to False. with open 语句默认的这个缺省参数[closefd] 为[True],会返回值的时候会自动去关闭文件操作。
写了一天才有此篇文章,若有不当之处请评论区斧正。
参考链接:
(1)、官方文档地址:JSON 编码和解码器