python的orjson
简介
首先我们先来了解下orjson的优缺点:
- 可以将datetime、date和time实例序列化为RFC 3339格式,例如:"2022-06-12T00:00:00+00:00"
- 序列化numpy.ndarray实例的速度比其他库快4-12倍,但使用的内存更少,约为其他库的1/3左右
- 输出速度是标准库的10到20倍
- 序列化的结果是bytes类型,而不是str
- 序列化str时,不会将unicode转义为ASCII
- 序列化float的速度是其他库的10倍,反序列化的速度是其他库的两倍
- 可以直接序列化str、int、list和dict的子类
- 不提供load( )和dump( )方法,在原生JSON库中,load( )方法可以把json格式的文件转换成python对象
- 序列化dataclass类型
import dataclasses, orjson, typing
@dataclasses.dataclass
class Member:
id: int
active: bool = dataclasses.field(default=False)
@dataclasses.dataclass
class Object:
id: int
name: str
members: typing.List[Member]
print(orjson.dumps(Object(1, "a", [Member(1, True), Member(2)])))
输出为:b'{"id":1,"name":"a","members":[{"id":1,"active":true},{"id":2,"active":false}]}'
- 序列化 float
orjson序列化和反序列化双精度浮点数,不会损失精度。当序列化NaN,Infinity,-Infinity时,会返回null。
>>> import orjson, ujson, rapidjson, json
>>> orjson.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
b'[null,null,null]'
>>> ujson.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
OverflowError: Invalid Inf value when encoding double
>>> rapidjson.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
'[NaN,Infinity,-Infinity]'
>>> json.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
'[NaN, Infinity, -Infinity]'
- 序列化Int类型
orjson可以对整数进行序列化和反序列化。但web浏览器只支持53-bit的整数,当值超过53-bit时会产生JSONEncodeError。
>>> import orjson
>>> orjson.dumps(9007199254740992)
b'9007199254740992'
>>> orjson.dumps(9007199254740992, option=orjson.OPT_STRICT_INTEGER)
JSONEncodeError: Integer exceeds 53-bit range
>>> orjson.dumps(-9007199254740992, option=orjson.OPT_STRICT_INTEGER)
JSONEncodeError: Integer exceeds 53-bit range
- numpy
序列化numpy数据需要设置option=orjson.OPT_SERIALIZE_NUMPY。
>>> import orjson, numpy
>>> orjson.dumps(
numpy.array([[1, 2, 3], [4, 5, 6]]),
option=orjson.OPT_SERIALIZE_NUMPY,
)
b'[[1,2,3],[4,5,6]]'
- str
orjson只处理UTF-8格式的字符串,如果给orjson.dumps()方法传入一个UTF-16的字符串,会产生报错。
>>> import orjson
>>> orjson.dumps('\ud800')
JSONEncodeError: str is not valid UTF-8: surrogates not allowed
- uuid
orjson可以把uuid.UUID实例序列化为RFC 4122格式。
>>> import orjson, uuid
>>> orjson.dumps(uuid.UUID('f81d4fae-7dec-11d0-a765-00a0c91e6bf6'))
b'"f81d4fae-7dec-11d0-a765-00a0c91e6bf6"'
>>> orjson.dumps(uuid.uuid5(uuid.NAMESPACE_DNS, "python.org"))
b'"886313e1-3b8a-5372-9b90-0c9aee199e5d"'
安装
orjson支持3.7-3.10所有版本64位的Python,注意32位的 Python 无法使用orjson!本文将在3.8.2环境下使用orjson,使用以下命令安装orjson:
pip install --upgrade "pip>=20.3"
pip install --upgrade orjson
使用
- 基本使用
我们首先使用orjson序列化一个字典,随后再将结果反序列化:
import orjson, datetime, numpy
data = {
"type": "job",
"created_at": datetime.datetime(2022, 6, 12),
"status": "",
"payload": numpy.array([[1, 2], [3, 4]]),
}
# 把python类型的数据转换成json形式,结果是bytes类型,而不是str
serialize = orjson.dumps(data, option=orjson.OPT_NAIVE_UTC | orjson.OPT_SERIALIZE_NUMPY)
print(serialize)
# 将序列化的结果转换为python数据
deserialize = orjson.loads(serialize)
print(deserialize)
输出结果为:
b'{"type":"job","created_at":"2022-06-12T00:00:00+00:00","status":"\xf0\x9f\x86\x97","payload":[[1,2],[3,4]]}'
{'type': 'job', 'created_at': '2022-06-12T00:00:00+00:00', 'status': '', 'payload': [[1, 2], [3, 4]]}
- 序列化
dumps( )可以将Python对象序列化为JSON数据,但与原生JSON库不同的是,orjson.dumps( )得到的JSON数据是bytes类型,少了将bytes转换为str的操作,因此,速度会大大加快。下面我们详细介绍下dumps( ):
def dumps(
__obj: Any,
default: Optional[Callable[[Any], Any]] = ...,
option: Optional[int] = ...,
) -> bytes: ...
(1) default 参数
我们先用dumps( )序列化一个Decimal类型的数据:
import orjson, decimal
orjson.dumps(decimal.Decimal("0.0842389659712649442845"))
会得到无法序列化Decimal类型的错误:
TypeError: Type is not JSON serializable: decimal.Decimal
这个时候,我们可以创建一个函数,将其作为default参数传递,来对Decimal进行序列化:
import orjson, decimal
def default(obj):
if isinstance(obj, decimal.Decimal):
return str(obj)
raise TypeError
res = orjson.dumps(decimal.Decimal("0.0842389659712649442845"), default=default)
print(res)
结果为:
b'"0.0842389659712649442845"'
(2) option参数
- 使用option参数可以定制序列化的结果。假如我们想在输出后面加上一个\n,可以使用OPT_APPEND_NEWLINE
import orjson
print(orjson.dumps([], option=orjson.OPT_APPEND_NEWLINE))
结果为:b'[]\n'
- OPT_OMIT_MICROSECONDS可以设置datetime.datetime实例的序列化结果没有微秒
import orjson, datetime
print(orjson.dumps(
datetime.datetime(2022, 6, 12, 0, 0, 0, 1),
option=orjson.OPT_OMIT_MICROSECONDS,
))
输出为:b'"2022-06-12T00:00:00"'
- 使用OPT_PASSTHROUGH_DATACLASS,可以定制化输出结果,假如数据中包含用户密码,我们需要在序列化后隐藏密码,可以这样做:
import orjson, dataclasses
@dataclasses.dataclass
class User:
id: str
name: str
password: str
def default(obj):
if isinstance(obj, User):
return {"id": obj.id, "name": obj.name}
raise TypeError
print(orjson.dumps(
User("3b1", "asd", "zxc"),
option=orjson.OPT_PASSTHROUGH_DATACLASS,
default=default,
))
输出的结果中就没有用户密码了:b'{"id":"3b1","name":"asd"}'
- OPT_PASSTHROUGH_DATETIME可以将日期格式化输出:
import orjson, datetime
def default(obj):
if isinstance(obj, datetime.datetime):
return obj.strftime("%a, %d %b %Y %H:%M:%S GMT")
raise TypeError
print(orjson.dumps(
{"创建时间": datetime.datetime(1970, 1, 1)},
option=orjson.OPT_PASSTHROUGH_DATETIME,
default=default,
))
输出为:b'{"创建时间":"Thu, 01 Jan 1970 00:00:00 GMT"}'
- OPT_SORT_KEYS可以将序列化结果的键值按顺序排列
import orjson
print(orjson.dumps({"b": 1, "c": 2, "a": 3}, option=orjson.OPT_SORT_KEYS))
- 1.
- 2.
输出为:b'{"a":3,"b":1,"c":2}'
- 反序列化
loads()可以将JSON数据转换为Python对象,该方法支持多种数据类型,包括:bytes, bytearray, memoryview, 和 str。
- 性能分析
我们用orjson, ujson, simplejson, json分别对一个列表进行序列化,该列表中有1000000个元素:
import orjson,time
import random
start = time.time()
data = [{
'id': 1,
'value': random.uniform(0,2000)
}
for i in range(1000000)]
orjson.dumps(data)
end = time.time()
print("总共耗时 " + str(round(end-start, 2)) + ' s')
python的orjson的更多相关文章
- (数据科学学习手札137)orjson:Python中最好用的json库
本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,我们在日常使用Pytho ...
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- Python 小而美的函数
python提供了一些有趣且实用的函数,如any all zip,这些函数能够大幅简化我们得代码,可以更优雅的处理可迭代的对象,同时使用的时候也得注意一些情况 any any(iterable) ...
- JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议
软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...
- 可爱的豆子——使用Beans思想让Python代码更易维护
title: 可爱的豆子--使用Beans思想让Python代码更易维护 toc: false comments: true date: 2016-06-19 21:43:33 tags: [Pyth ...
- 使用Python保存屏幕截图(不使用PIL)
起因 在极客学院讲授<使用Python编写远程控制程序>的课程中,涉及到查看被控制电脑屏幕截图的功能. 如果使用PIL,这个需求只需要三行代码: from PIL import Image ...
- Python编码记录
字节流和字符串 当使用Python定义一个字符串时,实际会存储一个字节串: "abc"--[97][98][99] python2.x默认会把所有的字符串当做ASCII码来对待,但 ...
- Apache执行Python脚本
由于经常需要到服务器上执行些命令,有些命令懒得敲,就准备写点脚本直接浏览器调用就好了,比如这样: 因为线上有现成的Apache,就直接放它里面了,当然访问安全要设置,我似乎别的随笔里写了安全问题,这里 ...
- python开发编译器
引言 最近刚刚用python写完了一个解析protobuf文件的简单编译器,深感ply实现词法分析和语法分析的简洁方便.乘着余热未过,头脑清醒,记下一点总结和心得,方便各位pythoner参考使用. ...
随机推荐
- C++源码中司空见惯的PIMPL是什么?
前言: C++源码中司空见惯的PIMPL是什么?用原始指针.std::unique_ptr和std::shared_ptr指向Implementation,会有什么不同?优缺点是什么?读完这篇文章,相 ...
- 10-04 NOIP模拟赛
10-04 NOIP模拟赛 喜提80+30+10=120分 T1 水管(flow) 题目描述 某国有 \(n\) 个城市,水利调配非常有问题,这导致部分地区出现严重的缺水,而部分地区却全年洪灾泛滥.政 ...
- foobar2000 v2.1.2 汉化版(更新日期: 2024.02.27)
新春佳节,送上一份新年礼物,祝您在新的一年里,万事如意,心想事成,身体健康,事业有成,财源广进,家庭和睦,笑容常开,好运连连. foobar2000 v2.1.2 汉化版 ---------- ...
- python模拟发送、消费kafka消息
参考文章: https://zhuanlan.zhihu.com/p/279784873 生产者代码: import traceback from kafka import KafkaProducer ...
- Effective C++:以const、enum和inline来替换define
替换define,也就是"以编译器替换预处理器".#define是C语言里的利器,但在C++里有很多取代它的理由. define是预处理的一部分,而不是编译器的一部分,它在编译前就 ...
- Java高并发,ArrayList、HashSet、HashMap不安全的集合类
首先是我们的ArrayList: 这次我们讲解的是集合的不安全,首先我们都知道ArrayList吧! List<String> list=new ArrayList<>(); ...
- mysql 备份还原命令备忘
1.备份 mysqldump -u username -p databasename tableName > backupfile.sql 2.还原 mysql -u username -p p ...
- Power BI如何连接MySQL数据库
既然写了如何卸载MySQL connector net(相关文章见如何解决MySQL Connector NET xxxx无法卸载的问题(win10)),那就顺便再写一篇Power BI(以下简称PB ...
- 使用wxpython开发跨平台桌面应用,基类对话框窗体的封装处理
在开发桌面界面的时候,往往都需要对一些通用的窗体进行一些抽象封装处理,以便统一界面效果,以及继承一些通用的处理过程,减少重复编码.本篇随笔介绍使用wxpython开发跨平台桌面应用,基类对话框窗体的封 ...
- 如何使用程序生成一个复杂的2D迷宫游戏地图
相关: I Solved The World's Hardest Maze (with Code) 本文不做过多的内容介绍,本文主要是分享上面的这个视频内容,该内容介绍了一些自动生成复杂2D迷宫的算法 ...