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""u5f20u4e09""age"28"gender""u7537""home""u5317u4eac"}
-------------- 以美观的形式打印 --------------
{
 "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""u5f20u4e09""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

2.1 安装

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

2.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":"xe5xbcxa0xe4xb8x89","age":18}' type: <class 'bytes'>
结果bytesstr:
 {"name":"张三","age":18}
列表map转json: b'[{"name":"xe5xbcxa0xe4xb8x89","age":18},{"name":"xe6x9dx8exe5x9bx9b","age":33},{"name":"xe7x8ex8bxe4xbax94","age":20}]' type: <class 'bytes'>
结果bytesstr:
 [{"name":"张三","age":18},{"name":"李四","age":33},{"name":"王五","age":20}]

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

2.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'>

2.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

2.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'>

2.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


Python常用库(四):json序列化和反序列
Python常用库(四):json序列化和反序列
微信搜一搜
 码记
“阅读原文”我们一起进步


原文始发于微信公众号(猿码记):Python常用库(四):json序列化和反序列

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/186160.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!