orjson 是一个快速、正确的 Python JSON 库。它被评为最快的 JSON Python 库,并且比标准 json 库或其他第三方库更正确。它本机序列化数据类、日期时间、numpy 和 UUID 实例。
orjson.dumps() 的速度大约是json
的 10 倍,序列化常见类型和子类型,有一个default
参数供调用者指定如何序列化任意类型,并且有许多控制输出的标志。
orjson.loads() 的速度大约是json
的 2 倍,并且严格符合 UTF-8 和 RFC 8259(“JavaScript 对象表示法 (JSON) 数据交换格式”)。
该库不提供文件、行分隔 JSON 文件等的读取和写入功能。
orjson 支持 CPython 3.8、3.9、3.10、3.11、3.12、3.13 和 3.14。
它分发适用于 Linux 的 amd64/x86_64、i686/x86、aarch64/armv8、arm7、POWER/ppc64le 和 s390x 轮子、适用于 macOS 的 amd64 和 aarch64 轮子以及适用于 Windows 的 amd64 和 i686/x86 轮子。
orjson 不支持也不会支持 PyPy、Android/iOS 的嵌入式 Python 构建或 PEP 554 子解释器。
版本遵循语义版本控制,并且在没有选择加入标志的情况下序列化新对象类型被视为重大更改。
orjson 已获得 Apache 2.0 和 MIT 许可证的许可。存储库和问题跟踪器是 github.com/ijl/orjson,补丁可以在那里提交。存储库中有一个可用的变更日志。
要从 PyPI 安装 Wheel,请安装orjson
包。
以requirements.in
或requirements.txt
格式指定:
orjson >= 3.10,<4
在pyproject.toml
格式中,指定:
orjson = " ^3.10 "
要制作轮子,请参阅包装。
这是指定选项的序列化和反序列化的示例:
> >> import orjson , datetime , numpy
> >> data = {
"type" : "job" ,
"created_at" : datetime . datetime ( 1970 , 1 , 1 ),
"status" : "?" ,
"payload" : numpy . array ([[ 1 , 2 ], [ 3 , 4 ]]),
}
> >> orjson . dumps ( data , option = orjson . OPT_NAIVE_UTC | orjson . OPT_SERIALIZE_NUMPY )
b'{"type":"job","created_at":"1970-01-01T00:00:00+00:00","status":" xf0 x9f x86 x97 ","payload":[[1,2],[3,4]]}'
> >> orjson . loads ( _ )
{ 'type' : 'job' , 'created_at' : '1970-01-01T00:00:00+00:00' , 'status' : '?' , 'payload' : [[ 1 , 2 ], [ 3 , 4 ]]}
orjson 版本 3 比版本 2 序列化更多类型。 str
、 int
、 dict
和list
的子类现在已序列化。这更快并且更类似于标准库。可以使用orjson.OPT_PASSTHROUGH_SUBCLASS
禁用它。 dataclasses.dataclass
实例现在默认序列化,并且无法在default
函数中自定义,除非指定option=orjson.OPT_PASSTHROUGH_DATACLASS
。默认情况下, uuid.UUID
实例是序列化的。对于现在序列化的任何类型,可以删除default
函数中的实现以及启用它们的选项,但这不是必须的。反序列化没有变化。
从标准库迁移,最大的区别是orjson.dumps
返回bytes
,而json.dumps
返回str
。
拥有使用非str
键的dict
对象的用户应指定option=orjson.OPT_NON_STR_KEYS
。
sort_keys
替换为option=orjson.OPT_SORT_KEYS
。
indent
由option=orjson.OPT_INDENT_2
替换,并且不支持其他级别的缩进。
ensure_ascii
目前可能不相关,并且 UTF-8 字符无法转义为 ASCII。
def dumps (
__obj : Any ,
default : Optional [ Callable [[ Any ], Any ]] = ...,
option : Optional [ int ] = ...,
) -> bytes : ...
dumps()
将 Python 对象序列化为 JSON。
它本机序列化str
、 dict
、 list
、 tuple
、 int
、 float
、 bool
、 None
、 dataclasses.dataclass
、 typing.TypedDict
、 datetime.datetime
、 datetime.date
、 datetime.time
、 uuid.UUID
、 numpy.ndarray
和orjson.Fragment
实例。它default
支持任意类型。它序列化str
、 int
、 dict
、 list
、 dataclasses.dataclass
和enum.Enum
的子类。它不会序列化tuple
的子类,以避免将namedtuple
对象序列化为数组。要避免序列化子类,请指定选项orjson.OPT_PASSTHROUGH_SUBCLASS
。
输出是包含 UTF-8 的bytes
对象。
全局解释器锁 (GIL) 在调用期间保持不变。
它会在不受支持的类型上引发JSONEncodeError
。此异常消息描述了无效对象,并带有错误消息Type is not JSON serializable: ...
。要解决此问题,请指定默认值。
它会在包含无效 UTF-8 的str
上引发JSONEncodeError
。
默认情况下,如果整数超过 64 位,或者使用OPT_STRICT_INTEGER
超过 53 位,则会引发JSONEncodeError
。
如果dict
具有str
以外类型的键,则会引发JSONEncodeError
,除非指定了OPT_NON_STR_KEYS
。
如果default
的输出递归到default
处理深度超过 254 层,则会引发JSONEncodeError
。
它会引发循环引用上的JSONEncodeError
。
如果不支持日期时间对象上的tzinfo
,则会引发JSONEncodeError
。
JSONEncodeError
是TypeError
的子类。这是为了与标准库兼容。
如果失败是由default
异常引起的,则JSONEncodeError
将原始异常链接为__cause__
。
要序列化子类或任意类型,请将default
指定为返回受支持类型的可调用对象。 default
可以是函数、lambda 或可调用类实例。要指定default
下不处理类型,请引发TypeError
等异常。
> >> import orjson , decimal
> >>
def default ( obj ):
if isinstance ( obj , decimal . Decimal ):
return str ( obj )
raise TypeError
> >> orjson . dumps ( decimal . Decimal ( "0.0842389659712649442845" ))
JSONEncodeError : Type is not JSON serializable : decimal . Decimal
> >> orjson . dumps ( decimal . Decimal ( "0.0842389659712649442845" ), default = default )
b'"0.0842389659712649442845"'
> >> orjson . dumps ({ 1 , 2 }, default = default )
orjson . JSONEncodeError : Type is not JSON serializable : set
default
可调用对象可能会返回一个对象,在引发异常之前, default
情况下该对象本身必须被处理最多 254 次。
如果无法处理类型, default
会引发异常,这一点很重要。否则,Python 会隐式返回None
,这对调用者来说就像一个合法值,并且被序列化:
> >> import orjson , json
> >>
def default ( obj ):
if isinstance ( obj , decimal . Decimal ):
return str ( obj )
> >> orjson . dumps ({ "set" :{ 1 , 2 }}, default = default )
b'{"set":null}'
> >> json . dumps ({ "set" :{ 1 , 2 }}, default = default )
'{"set":null}'
要修改数据的序列化方式,请指定option
。每个option
都是orjson
中的整数常量。要指定多个选项,请将它们屏蔽在一起,例如option=orjson.OPT_STRICT_INTEGER | orjson.OPT_NAIVE_UTC
。
将n
附加到输出。这是dumps(...) + "n"
模式的便利和优化。 bytes
对象是不可变的,此模式复制原始内容。
> >> import orjson
> >> orjson . dumps ([])
b"[]"
> >> orjson . dumps ([], option = orjson . OPT_APPEND_NEWLINE )
b"[] n "
漂亮的打印输出,缩进两个空格。这相当于标准库中的indent=2
。漂亮的打印速度较慢,输出较大。 orjson 是漂亮打印方面最快的比较库,并且与标准库相比,漂亮打印的速度减慢要少得多。此选项与所有其他选项兼容。
> >> import orjson
> >> orjson . dumps ({ "a" : "b" , "c" : { "d" : True }, "e" : [ 1 , 2 ]})
b'{"a":"b","c":{"d":true},"e":[1,2]}'
> >> orjson . dumps (
{ "a" : "b" , "c" : { "d" : True }, "e" : [ 1 , 2 ]},
option = orjson . OPT_INDENT_2
)
b'{ n "a": "b", n "c": { n "d": true n }, n "e": [ n 1, n 2 n ] n }'
如果显示,缩进和换行将如下所示:
{
"a" : " b " ,
"c" : {
"d" : true
},
"e" : [
1 ,
2
]
}
这测量将 github.json 设备序列化为紧凑型 (52KiB) 或漂亮型 (64KiB):
图书馆 | 紧凑(毫秒) | 漂亮(女士) | 与 orjson |
---|---|---|---|
或json | 0.01 | 0.02 | 1 |
json | 0.13 | 0.54 | 34 |
这测量序列化 citm_catalog.json 固定装置,由于嵌套和换行的数量,更糟糕的情况是紧凑(489KiB)或漂亮(1.1MiB):
图书馆 | 紧凑(毫秒) | 漂亮(女士) | 与 orjson |
---|---|---|---|
或json | 0.25 | 0.45 | 1 |
json | 3.01 | 24.42 | 54.4 |
这可以使用pyindent
脚本来重现。
将没有tzinfo
datetime.datetime
对象序列化为 UTC。这对设置了tzinfo
的datetime.datetime
对象没有影响。
> >> import orjson , datetime
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 ),
)
b'"1970-01-01T00:00:00"'
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 ),
option = orjson . OPT_NAIVE_UTC ,
)
b'"1970-01-01T00:00:00+00:00"'
序列化str
以外类型的dict
键。这允许dict
键为str
、 int
、 float
、 bool
、 None
、 datetime.datetime
、 datetime.date
、 datetime.time
、 enum.Enum
和uuid.UUID
之一。为了进行比较,标准库默认序列化str
、 int
、 float
、 bool
或None
。 orjson 基准测试认为序列化非str
键比其他库更快。对于str
键,此选项比默认选项慢。
> >> import orjson , datetime , uuid
> >> orjson . dumps (
{ uuid . UUID ( "7202d115-7ff3-4c81-a7c1-2a1f067b1ece" ): [ 1 , 2 , 3 ]},
option = orjson . OPT_NON_STR_KEYS ,
)
b'{"7202d115-7ff3-4c81-a7c1-2a1f067b1ece":[1,2,3]}'
> >> orjson . dumps (
{ datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 ): [ 1 , 2 , 3 ]},
option = orjson . OPT_NON_STR_KEYS | orjson . OPT_NAIVE_UTC ,
)
b'{"1970-01-01T00:00:00+00:00":[1,2,3]}'
这些类型通常按照值的方式进行序列化,例如, datetime.datetime
仍然是 RFC 3339 字符串并尊重影响它的选项。例外情况是int
序列化不遵守OPT_STRICT_INTEGER
。
此选项存在创建重复键的风险。这是因为非str
对象可能会序列化为与现有键相同的str
,例如{"1": true, 1: false}
。要插入到dict
中的最后一个键将最后被序列化,并且 JSON 反序列化器可能会获取最后一次出现的键(在上面, false
)。第一个值将丢失。
此选项与orjson.OPT_SORT_KEYS
兼容。如果使用排序,请注意排序不稳定,并且对于重复键将是不可预测的。
> >> import orjson , datetime
> >> orjson . dumps (
{ "other" : 1 , datetime . date ( 1970 , 1 , 5 ): 2 , datetime . date ( 1970 , 1 , 3 ): 3 },
option = orjson . OPT_NON_STR_KEYS | orjson . OPT_SORT_KEYS
)
b'{"1970-01-03":3,"1970-01-05":2,"other":1}'
该方法测量序列化 589KiB 的 JSON,其中包含 100 个dict
的list
,其中每个dict
都有 365 个代表纪元时间戳的随机排序的int
键以及一个str
键,每个键的值都是一个整数。在“strkeys”中,键在序列化之前被转换为str
,并且orjson仍然指定option=orjson.OPT_NON_STR_KEYS
(这总是有点慢)。
图书馆 | str 键(毫秒) | 整数键(毫秒) | int 键已排序(毫秒) |
---|---|---|---|
或json | 0.5 | 0.93 | 2.08 |
json | 2.72 | 3.59 |
json 为空,因为在将所有键转换为str
之前尝试排序时会引发TypeError
。这可以使用pynonstr
脚本重现。
不要序列化datetime.datetime
和datetime.time
实例上的microsecond
字段。
> >> import orjson , datetime
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , 1 ),
)
b'"1970-01-01T00:00:00.000001"'
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , 1 ),
option = orjson . OPT_OMIT_MICROSECONDS ,
)
b'"1970-01-01T00:00:00"'
将dataclasses.dataclass
实例传递给default
。这允许自定义它们的输出,但速度要慢得多。
> >> 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
> >> orjson . dumps ( User ( "3b1" , "asd" , "zxc" ))
b'{"id":"3b1","name":"asd","password":"zxc"}'
> >> orjson . dumps ( User ( "3b1" , "asd" , "zxc" ), option = orjson . OPT_PASSTHROUGH_DATACLASS )
TypeError : Type is not JSON serializable : User
> >> orjson . dumps (
User ( "3b1" , "asd" , "zxc" ),
option = orjson . OPT_PASSTHROUGH_DATACLASS ,
default = default ,
)
b'{"id":"3b1","name":"asd"}'
将datetime.datetime
、 datetime.date
和datetime.time
实例传递为default
。这允许将日期时间序列化为自定义格式,例如 HTTP 日期:
> >> import orjson , datetime
> >>
def default ( obj ):
if isinstance ( obj , datetime . datetime ):
return obj . strftime ( "%a, %d %b %Y %H:%M:%S GMT" )
raise TypeError
> >> orjson . dumps ({ "created_at" : datetime . datetime ( 1970 , 1 , 1 )})
b'{"created_at":"1970-01-01T00:00:00"}'
> >> orjson . dumps ({ "created_at" : datetime . datetime ( 1970 , 1 , 1 )}, option = orjson . OPT_PASSTHROUGH_DATETIME )
TypeError : Type is not JSON serializable : datetime . datetime
> >> orjson . dumps (
{ "created_at" : datetime . datetime ( 1970 , 1 , 1 )},
option = orjson . OPT_PASSTHROUGH_DATETIME ,
default = default ,
)
b'{"created_at":"Thu, 01 Jan 1970 00:00:00 GMT"}'
如果使用 OPT_NON_STR_KEYS,这不会影响dict
键中的日期时间。
将内置类型的子类传递给default
。
> >> import orjson
> >>
class Secret ( str ):
pass
def default ( obj ):
if isinstance ( obj , Secret ):
return "******"
raise TypeError
> >> orjson . dumps ( Secret ( "zxc" ))
b'"zxc"'
> >> orjson . dumps ( Secret ( "zxc" ), option = orjson . OPT_PASSTHROUGH_SUBCLASS )
TypeError : Type is not JSON serializable : Secret
> >> orjson . dumps ( Secret ( "zxc" ), option = orjson . OPT_PASSTHROUGH_SUBCLASS , default = default )
b'"******"'
如果使用 OPT_NON_STR_KEYS,这不会影响将子类序列化为dict
键。
这已被弃用,并且在版本 3 中无效。在版本 2 中,序列化dataclasses.dataclass
实例需要这样做。有关更多信息,请参阅数据类。
序列化numpy.ndarray
实例。有关更多信息,请参阅 numpy.
这已被弃用,并且在版本 3 中无效。在版本 2 中,序列化uuid.UUID
实例需要这样做。有关更多信息,请参阅 UUID。
按排序顺序序列化dict
键。默认是以未指定的顺序进行序列化。这相当于标准库中的sort_keys=True
。
这可用于确保散列或测试的顺序是确定的。它会严重影响性能,一般不推荐使用。
> >> import orjson
> >> orjson . dumps ({ "b" : 1 , "c" : 2 , "a" : 3 })
b'{"b":1,"c":2,"a":3}'
> >> orjson . dumps ({ "b" : 1 , "c" : 2 , "a" : 3 }, option = orjson . OPT_SORT_KEYS )
b'{"a":3,"b":1,"c":2}'
这措施序列化 twitter.json 固定装置未排序和排序:
图书馆 | 未排序(毫秒) | 已排序(毫秒) | 与 orjson |
---|---|---|---|
或json | 0.11 | 0.3 | 1 |
json | 1.36 | 1.93 | 6.4 |
可以使用pysort
脚本重现基准测试。
排序不支持排序规则/区域设置:
> >> import orjson
> >> orjson . dumps ({ "a" : 1 , "ä" : 2 , "A" : 3 }, option = orjson . OPT_SORT_KEYS )
b'{"A":3,"a":1," xc3 xa4 ":2}'
这与标准库的排序行为相同。
dataclass
也序列化为映射,但这对它们没有影响。
对整数强制 53 位限制。否则限制为 64 位,与 Python 标准库相同。有关更多信息,请参阅 int.
将datetime.datetime
实例上的 UTC 时区序列化为Z
而不是+00:00
。
> >> import orjson , datetime , zoneinfo
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , tzinfo = zoneinfo . ZoneInfo ( "UTC" )),
)
b'"1970-01-01T00:00:00+00:00"'
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , tzinfo = zoneinfo . ZoneInfo ( "UTC" )),
option = orjson . OPT_UTC_Z
)
b'"1970-01-01T00:00:00Z"'
orjson.Fragment
包含文档中已序列化的 JSON。这是一种包含来自缓存、JSONB 字段或单独序列化对象的 JSON blob 的有效方法,无需先通过loads()
反序列化为 Python 对象。
> >> import orjson
> >> orjson . dumps ({ "key" : "zxc" , "data" : orjson . Fragment ( b'{"a": "b", "c": 1}' )})
b'{"key":"zxc","data":{"a": "b", "c": 1}}'
它不会重新格式化: orjson.OPT_INDENT_2
不会影响紧凑型 blob,也不会将打印精美的 JSON blob 重写为紧凑型。
输入必须是bytes
或str
并作为位置参数给出。
如果给出了str
并且输入不是有效的 UTF-8,则会引发orjson.JSONEncodeError
。否则它不会进行验证,并且可能会编写无效的 JSON。这不会转义字符。该实现经过测试,如果给出无效字符串或无效 JSON,则不会崩溃。
def loads ( __obj : Union [ bytes , bytearray , memoryview , str ]) -> Any : ...
loads()
将 JSON 反序列化为 Python 对象。它反序列化为dict
、 list
、 int
、 float
、 str
、 bool
和None
对象。
接受bytes
、 bytearray
、 memoryview
和str
输入。如果输入以memoryview
、 bytearray
或bytes
对象的形式存在,建议直接传递这些对象,而不是创建不必要的str
对象。也就是说, orjson.loads(b"{}")
而不是orjson.loads(b"{}".decode("utf-8"))
。这具有较低的内存使用率和较低的延迟。
输入必须是有效的 UTF-8。
orjson 在整个过程期间维护映射键的缓存。通过避免重复的字符串,这会导致内存使用量的净减少。密钥必须最多为 64 字节才能缓存,并存储 2048 个条目。
全局解释器锁 (GIL) 在调用期间保持不变。
如果给定无效类型或无效 JSON,则会引发JSONDecodeError
。这包括输入是否包含NaN
、 Infinity
或-Infinity
,这是标准库允许的,但不是有效的 JSON。
如果数组或对象的组合递归 1024 层深度,则会引发JSONDecodeError
。
JSONDecodeError
是json.JSONDecodeError
和ValueError
的子类。这是为了与标准库兼容。
orjson 本机序列化dataclasses.dataclass
的实例。与序列化dict
相比,它序列化实例的速度是其他库的 40-50 倍,并且避免了其他库中出现的严重减速。
支持传递数据类的所有变体,包括使用__slots__
数据类、冻结数据类、具有可选或默认属性的数据类以及子类。不使用__slots__
会带来性能优势。
图书馆 | 听写(毫秒) | 数据类(毫秒) | 与 orjson |
---|---|---|---|
或json | 0.43 | 0.95 | 1 |
json | 5.81 | 38.32 | 40 |
这测量了序列化 555KiB 的 JSON、或本机 json 以及其他库,使用default
序列化dataclasses.asdict()
的输出。这可以使用pydataclass
脚本来重现。
数据类被序列化为映射,每个属性都按照类定义中给出的顺序进行序列化:
> >> 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 ]
> >> orjson . dumps ( Object ( 1 , "a" , [ Member ( 1 , True ), Member ( 2 )]))
b'{"id":1,"name":"a","members":[{"id":1,"active":true},{"id":2,"active":false}]}'
orjson 将datetime.datetime
对象序列化为 RFC 3339 格式,例如“1970-01-01T00:00:00+00:00”。这是 ISO 8601 的子集,与标准库中的isoformat()
兼容。
> >> import orjson , datetime , zoneinfo
> >> orjson . dumps (
datetime . datetime ( 2018 , 12 , 1 , 2 , 3 , 4 , 9 , tzinfo = zoneinfo . ZoneInfo ( "Australia/Adelaide" ))
)
b'"2018-12-01T02:03:04.000009+10:30"'
> >> orjson . dumps (
datetime . datetime ( 2100 , 9 , 1 , 21 , 55 , 2 ). replace ( tzinfo = zoneinfo . ZoneInfo ( "UTC" ))
)
b'"2100-09-01T21:55:02+00:00"'
> >> orjson . dumps (
datetime . datetime ( 2100 , 9 , 1 , 21 , 55 , 2 )
)
b'"2100-09-01T21:55:02"'
datetime.datetime
支持tzinfo
为None
、 datetime.timezone.utc
的实例、来自 python3.9+ zoneinfo
模块的时区实例或来自第三方pendulum
、 pytz
或dateutil
/ arrow
库的时区实例。
对于时区,使用标准库的zoneinfo.ZoneInfo
是最快的。
datetime.time
对象不得具有tzinfo
。
> >> import orjson , datetime
> >> orjson . dumps ( datetime . time ( 12 , 0 , 15 , 290 ))
b'"12:00:15.000290"'
datetime.date
对象将始终序列化。
> >> import orjson , datetime
> >> orjson . dumps ( datetime . date ( 1900 , 1 , 2 ))
b'"1900-01-02"'
tzinfo
错误会导致引发JSONEncodeError
。
要禁用datetime
对象的序列化,请指定选项orjson.