Python常用库(四):json序列化和反序列

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 = [123456789]
    # 列表转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: [123456789]
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转列表:[123456789] 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 = [123456789]
    # 列表转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转列表:[123456789] 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

本文由 mdnice 多平台发布

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值