1. 标准库:json

1.1 参数说明

参数 说明
skipkeys 如果为True的话,则只能是字典对象,否则会TypeError错误, 默认False
ensure_ascii 确定是否为ASCII编码,设置True时,汉字会正常显示
check_circular 循环类型检查,如果为True的话
allow_nan 确定是否为允许的值
indent 当设置True时,会以美观的方式来打印Json
separators 对象分隔符,默认为,
sort_keys 当设置True字时,字典对象会按照键的ASCII码来排序
if __name__ == '__main__':
print("-------------- 以默认形式打印 --------------")
mapVar = {"name": "张三", "age": 28, "gender": "男", "home": "北京"}
# 以默认形式打印
print(json.dumps(mapVar))
# 以美观的形式打印
print("-------------- 以美观的形式打印 --------------")
print(json.dumps(mapVar, indent=True, ensure_ascii=False))
# 当设置True字时,字典对象会按照键的ASCII码来排序
print("-------------- 字典对象会按照键ASCII码来排序 --------------")
print(json.dumps(mapVar, indent=True, ensure_ascii=False, sort_keys=True))

# ************************** 输出 **************************
-------------- 以默认形式打印 --------------
{"name": "\u5f20\u4e09", "age": 28, "gender": "\u7537", "home": "\u5317\u4eac"}
-------------- 以美观的形式打印 --------------
{
"name": "张三",
"age": 28,
"gender": "男",
"home": "北京"
}
-------------- 字典对象会按照键ASCII码来排序 --------------
{
"age": 28,
"gender": "男",
"home": "北京",
"name": "张三"
}

1.2 变量转Json

import json

if __name__ == '__main__':
listVar = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 列表转json
print('列表转json:', json.dumps(listVar))
# map 转json
mapVar = {'name': '张三', 'age': 18}
print('map转json:', json.dumps(mapVar))
print('map转json-汉字不转义:', json.dumps(mapVar, ensure_ascii=False))
# 列表map转json
listMapVar = [
{'name': '张三', 'age': 18},
{'name': '李四', 'age': 33},
{'name': '王五', 'age': 20},
]
print('列表map转json:', json.dumps(listMapVar, ensure_ascii=False))

# ----------------- 输出 ---------------------
列表转json: [1, 2, 3, 4, 5, 6, 7, 8, 9]
map转json: {"name": "\u5f20\u4e09", "age": 18}
map转json-汉字不转义: {"name": "张三", "age": 18}
列表map转json: [{"name": "张三", "age": 18}, {"name": "李四", "age": 33}, {"name": "王五", "age": 20}]

1.3 Json转变量

import json

if __name__ == '__main__':
# json转列表
listJsonStr = '[1, 2, 3, 4, 5, 6, 7, 8, 9]'
res = json.loads(listJsonStr)
print('json转列表:{} type:{}'.format(res, type(res)))
# json转字典
dictJsonStr = '{"name": "张三", "age": 18}'
res2 = json.loads(dictJsonStr)
print('json转字典:{} type:{}'.format(res2, type(res2)))

# ----------------- 输出 ---------------------
json转列表:[1, 2, 3, 4, 5, 6, 7, 8, 9] type:<class 'list'>
json转字典:{'name': '张三', 'age': 18} type:<class 'dict'>

1.4 读写Json文件

import json
import os
import time

if __name__ == '__main__':
# json文件位置
jsonFile = os.path.join(os.getcwd(), "test.json")
if not os.path.exists(jsonFile):
# 创建文件
open(jsonFile, "w").close()

# 写json文件
with open(jsonFile, "w") as f:
stu = {'name': '张三', 'time': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}
# 写入
print("写入json内容:", stu)
json.dump(stu, f, ensure_ascii=False)

time.sleep(3)
print("--------------------- 暂停3秒 ---------------------")
# 读取json文件内容
with open(jsonFile, "r") as f:
result = json.load(f)
print("读取json内容:", result)

# ----------------- 输出 ---------------------
写入json内容: {'name': '张三', 'time': '2023-09-01 00:02:24'}
--------------------- 暂停3秒 ---------------------
读取json内容: {'name': '张三', 'time': '2023-09-01 00:02:24'}

1.5 类对象转Json

import json

class Student:
def __init__(self, name: str, age: int, phone: str):
self.name = name
self.age = age
self.__phone = phone

@property
def tojson(self):
return {
'name': self.name,
'age': self.age,
'phone': self.__phone
}


if __name__ == '__main__':
stu = Student("张三", 22, "17600000111")
print("*************** 第一种方式: __dict__ *****************")
print(json.dumps(stu.__dict__, indent=True, ensure_ascii=False))

print("*************** 第二种方式: 自定义方法 *****************")
print(json.dumps(stu.tojson, indent=True, ensure_ascii=False))

# -------------------- 输出 --------------------
*************** 第一种方式: __dict__ *****************
{
"name": "张三",
"age": 22,
"_Student__phone": "17600000111"
}
*************** 第二种方式: 自定义方法 *****************
{
"name": "张三",
"age": 22,
"phone": "17600000111"
}

1.6 Json转类对象

if __name__ == '__main__':
jsonString = '{"name":"张三","age":22,"phone":"177777777777"}'
jsonData = json.loads(jsonString)
s = Student(jsonData['name'], jsonData['age'], jsonData['phone'])
print("s.type: ", type(s))
print("s.name: ", s.name)
print("s.age: ", s.age)

# -------------------- 输出 --------------------
s.type: <class '__main__.Student'>
s.name: 张三
s.age: 22

2. 开源库:orjosn

orjson是一个JSON库,相较于Python原生的JSON库,它的功能更加丰富、效率更高。

Github(截止当前4.9k): https://github.com/ijl/orjson

5.1 安装

# 使用pip 安装
$ pip install --upgrade orjson
# 使用
$ conda install orjson

5.2 变量转json

import orjson

if __name__ == '__main__':
listVar = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 列表转json
listJson = orjson.dumps(listVar)
print('列表转json:', listJson, 'type:', type(listJson))
print('结果bytes转str:', listJson.decode('utf-8'))

# map 转json
mapVar = {'name': '张三', 'age': 18}
mapJson = orjson.dumps(mapVar)
print('map转json:', mapJson, 'type:', type(mapJson))
print('结果bytes转str:', mapJson.decode('utf-8'))

# 列表map转json
listMapVar = [
{'name': '张三', 'age': 18},
{'name': '李四', 'age': 33},
{'name': '王五', 'age': 20},
]
listMapVarJson = orjson.dumps(listMapVar)
print('列表map转json:', listMapVarJson, 'type:', type(listMapVarJson))
print('结果bytes转str:', listMapVarJson.decode('utf-8'))

# -------------------- 输出 -------------------
列表转json: b'[1,2,3,4,5,6,7,8,9]' type: <class 'bytes'>
结果bytesstr: [1,2,3,4,5,6,7,8,9]
map转json: b'{"name":"\xe5\xbc\xa0\xe4\xb8\x89","age":18}' type: <class 'bytes'>
结果bytesstr: {"name":"张三","age":18}
列表map转json: b'[{"name":"\xe5\xbc\xa0\xe4\xb8\x89","age":18},{"name":"\xe6\x9d\x8e\xe5\x9b\x9b","age":33},{"name":"\xe7\x8e\x8b\xe4\xba\x94","age":20}]' type: <class 'bytes'>
结果bytesstr: [{"name":"张三","age":18},{"name":"李四","age":33},{"name":"王五","age":20}]

@注: 通过上面示例可以发现,序列化后的数据类型为bytes,需要通过x.decode('utf-8')转str

5.3 json转变量

if __name__ == '__main__':
# json转列表
listJsonStr = '[1, 2, 3, 4, 5, 6, 7, 8, 9]'
res = orjson.loads(listJsonStr)
print('json转列表:{} type:{}'.format(res, type(res)))
# json转字典
dictJsonStr = '{"name": "张三", "age": 18}'
res2 = orjson.loads(dictJsonStr)
print('json转字典:{} type:{}'.format(res2, type(res2)))
# json转字典列表
mapListJsonStr = '''[{"name":"张三","age":18},{"name":"李四","age":33},{"name":"王五","age":20}]'''
res3 = orjson.loads(mapListJsonStr)
print('json转字典列表:{} type:{}'.format(res3, type(res3)))

# --------------------------- 输出 --------------------------
json转列表:[1, 2, 3, 4, 5, 6, 7, 8, 9] type:<class 'list'>
json转字典:{'name': '张三', 'age': 18} type:<class 'dict'>
json转字典列表:[{'name': '张三', 'age': 18}, {'name': '李四', 'age': 33}, {'name': '王五', 'age': 20}] type:<class 'list'>

5.4 类对象转json

import dataclasses
import orjson

@dataclasses.dataclass
class Student:
def __init__(self, name: str, age: int, phone: str):
self.name = name
self.age = age
self.__phone = phone

if __name__ == '__main__':
# json转列表
stu = Student("小英", 18, "17600000000")
jsonRes = orjson.dumps(stu).decode("utf-8")
print("jsonRes:", jsonRes, "type", type(jsonRes))

# --------------------------- 输出 --------------------------
jsonRes: {"name":"小英","age":18} type <class 'str'>

@提示: 上面是实例会发现,私有属性不会被序列化成json

@注:使用orjson把类转json时,需要给类加上装饰器: @dataclasses.dataclass,否则会报下面错误:

Traceback (most recent call last): File "/Users/liuqh/ProjectItem/PythonItem/python-learn/main.py", line 26, in <module> jsonRes = orjson.dumps(stu).decode("utf-8") ^^^^^^^^^^^^^^^^^ TypeError: Type is not JSON serializable: Student

5.5 嵌套类对象转json

import dataclasses
import typing
from dataclasses import field
import orjson

@dataclasses.dataclass
class Score:
key: str
value: int = field(default=0)

@dataclasses.dataclass
class Student:
score: typing.List[Score]

def __init__(self, name: str, scoreList: typing.List[Score]):
self.name = name
self.score = scoreList

if __name__ == '__main__':
# json转列表
stu = Student("小英", [Score("语文", 88), Score("英语", 75), Score("数学", 92)])
jsonRes = orjson.dumps(stu).decode("utf-8")
print("jsonRes:", jsonRes, "type", type(jsonRes))

# --------------------------- 输出 --------------------------
jsonRes: {"name":"小英","score":[{"key":"语文","value":88},{"key":"英语","value":75},{"key":"数学","value":92}]} type <class 'str'>

5.6 OPTION选项使用

参数 说明
orjson.OPT_INDENT_2 美化json打印输出
orjson.OPT_SORT_KEYS 可以对序列化后的结果自动按照键进行排序
orjson.OPT_PASSTHROUGH_DATETIME 结合default对日期格式做处理
import orjson
from datetime import datetime

def formatTimeHandler(obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')

if __name__ == '__main__':
listMapVar = {'name': '张三', 'age': 18, 'home': '北京昌平', 'sex': '男'}
# 美化和排序
jsonRes = orjson.dumps(listMapVar, option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS).decode("utf-8")
print(jsonRes)
# 时间格式化
timeMapVar = {'time': datetime.now()}
r2 = orjson.dumps(timeMapVar, option=orjson.OPT_PASSTHROUGH_DATETIME, default=formatTimeHandler).decode("utf-8")
print(r2)
# --------------------------- 输出 --------------------------
{
"age": 18,
"home": "北京昌平",
"name": "张三",
"sex": "男"
}
{"time":"2023-09-05 00:09:19"}

更多使用方法,参见https://github.com/ijl/orjson