跳转到主要内容

快速、正确的Python JSON库,支持dataclasses、datetimes和numpy

项目描述

orjson

orjson 是一个快速、正确的Python JSON库。它在性能基准测试中被证明是Python中最快的JSON库,并且比标准json库或其他第三方库更准确。它可以原生序列化dataclassdatetimenumpyUUID实例。

与其它Python JSON库相比,其特性和缺点

  • 序列化 dataclass 实例的速度比其他库快40-50倍
  • datetimedatetime 实例序列化为RFC 3339格式,例如,“1970-01-01T00:00:00+00:00”
  • 以0.3倍其他库的内存使用率,将 numpy.ndarray 实例序列化速度快4-12倍
  • 比标准库快10-20倍进行美化打印
  • 序列化为bytes而不是str,即不是直接替换
  • 不转义Unicode为ASCII序列化str,例如,“好”而不是“\\u597d”
  • 序列化float比其他库快10倍,反序列化比其他库快一倍
  • 原生序列化strintlistdict的子类,需要使用default指定如何序列化其他类型
  • 使用default钩子序列化任意类型
  • 具有严格的UTF-8兼容性,比标准库更正确
  • 严格遵循JSON规范,不支持Nan/Infinity/-Infinity
  • 在53位整数上具有严格的JSON兼容性,默认支持64位
  • 不提供从/向文件对象读写操作的load()dump()函数

orjson支持CPython 3.8、3.9、3.10、3.11、3.12和3.13。它为Linux提供amd64/x86_64、aarch64/armv8、arm7、POWER/ppc64le和s390x的wheels,为macOS提供amd64和aarch64的wheels,为Windows提供amd64和i686/x86的wheels。orjson不支持也不将支持PyPy。orjson不支持也不将支持PEP 554子解释器。发布遵循语义版本控制,不通过opt-in标志序列化新的对象类型被视为破坏性变更。

orjson同时受Apache 2.0和MIT许可协议的约束。仓库和问题跟踪器位于github.com/ijl/orjson,补丁可以提交到那里。仓库中提供了一个变更日志

  1. 用法
    1. 安装
    2. 快速入门
    3. 迁移
    4. 序列化
      1. 默认
      2. 选项
      3. 片段
    5. 反序列化
  2. 类型
    1. 数据类
    2. 日期时间
    3. 枚举
    4. 浮点数
    5. 整数
    6. NumPy
    7. 字符串
    8. UUID
  3. 测试
  4. 性能
    1. 延迟
    2. 内存
    3. 重现
  5. 问题
  6. 打包
  7. 许可证

用法

安装

要从PyPI安装wheel,请参阅

pip install --upgrade "pip>=20.3" # manylinux_x_y, universal2 wheel support
pip install --upgrade orjson

要构建wheel,请参阅打包

快速入门

这是一个序列化示例,其中指定了选项,并进行了反序列化

>>> 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序列化更多类型。现在序列化了strintdictlist的子类。这比标准库更快,更相似。可以通过orjson.OPT_PASSTHROUGH_SUBCLASS禁用。默认情况下,dataclasses.dataclass实例会被序列化,并且在默认函数中不能自定义,除非指定了option=orjson.OPT_PASSTHROUGH_DATACLASS。默认情况下,uuid.UUID实例会被序列化。对于现在被序列化的任何类型,可以在default函数中移除其实现和启用它们的选项,但不需要这么做。反序列化没有变化。

要从标准库迁移,最大的不同是orjson.dumps返回bytes,而json.dumps返回一个str。使用非str键的dict对象应指定option=orjson.OPT_NON_STR_KEYSsort_keysoption=orjson.OPT_SORT_KEYS替换。indentoption=orjson.OPT_INDENT_2替换,其他级别的缩进不受支持。

序列化

def dumps(
    __obj: Any,
    default: Optional[Callable[[Any], Any]] = ...,
    option: Optional[int] = ...,
) -> bytes: ...

dumps()将Python对象序列化为JSON。

它原生序列化strdictlisttupleintfloatboolNonedataclasses.dataclasstyping.TypedDictdatetime.datetimedatetime.datedatetime.timeuuid.UUIDnumpy.ndarrayorjson.Fragment实例。它通过default支持任意类型。它序列化strintdictlistdataclasses.dataclassenum.Enum的子类。为了避免序列化子类,指定选项orjson.OPT_PASSTHROUGH_SUBCLASS

输出是一个包含UTF-8的bytes对象。

在调用期间,全局解释器锁(GIL)被持有。

在不受支持的类型上引发JSONEncodeError。此异常消息描述了包含错误消息类型不是可JSON序列化的:...的无效对象。要修复此问题,请指定默认值

如果字符串包含无效的UTF-8,则引发JSONEncodeError

默认情况下,它会在超过64位或使用OPT_STRICT_INTEGER时超过53位的整数上引发JSONEncodeError

如果字典的键类型不是str,除非指定了OPT_NON_STR_KEYS,否则将引发JSONEncodeError

如果default的输出递归到default处理超过254层,则引发JSONEncodeError

在循环引用上引发JSONEncodeError

如果datetime对象上的tzinfo不受支持,则引发JSONEncodeError

JSONEncodeErrorTypeError的子类。这是为了与标准库兼容。

如果失败是由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, rapidjson
>>>
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}'
>>> rapidjson.dumps({"set":{1, 2}}, default=default)
'{"set":null}'

选项

要修改数据序列化方式,指定option。每个optionorjson中的整数常量。要指定多个选项,将它们掩码在一起,例如:option=orjson.OPT_STRICT_INTEGER | orjson.OPT_NAIVE_UTC

OPT_APPEND_NEWLINE

\n追加到输出。这是一个方便的优化,用于dumps(...) + "\n"的模式。bytes对象是不可变的,此模式会复制原始内容。

>>> import orjson
>>> orjson.dumps([])
b"[]"
>>> orjson.dumps([], option=orjson.OPT_APPEND_NEWLINE)
b"[]\n"
OPT_INDENT_2

使用两个空格的缩进格式化输出。这相当于标准库中的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)

紧凑型(ms) 格式化型(ms) 与orjson相比
orjson 0.03 0.04 1
ujson 0.18 0.19 4.6
rapidjson 0.1 0.12 2.9
simplejson 0.25 0.89 21.4
json 0.18 0.71 17

这衡量了将citm_catalog.json固定序列化为紧凑型(489KiB)或格式化型(1.1MiB),这更像是最坏的情况,因为嵌套和换行符的数量较多

紧凑型(ms) 格式化型(ms) 与orjson相比
orjson 0.59 0.71 1
ujson 2.9 3.59 5
rapidjson 1.81 2.8 3.9
simplejson 10.43 42.13 59.1
json 4.16 33.42 46.9

这可以使用pyindent脚本来重现。

OPT_NAIVE_UTC

将没有tzinfodatetime.datetime对象序列化为UTC。这不会影响设置了tzinfodatetime.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"'
OPT_NON_STR_KEYS

序列化除str类型以外的dict键。这允许dict键可以是以下类型之一:strintfloatboolNonedatetime.datetimedatetime.datedatetime.timeenum.Enumuuid.UUID。相比之下,标准库默认序列化strintfloatboolNone。orjson的基准测试表明,在序列化非str键方面,orjson比其他库更快。对于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个dictlist,每个dict都有365个随机排序的int键,这些键表示纪元时间戳,以及一个str键。对于“str keys”,在序列化之前将键转换为str,并且orjson仍然指定option=orjson.OPT_NON_STR_KEYS(这总是稍微慢一些)。

str键(毫秒) int键(毫秒) 排序后的int键(毫秒)
orjson 1.53 2.16 4.29
ujson 3.07 5.65
rapidjson 4.29
simplejson 11.24 14.50 21.86
json 7.17 8.49

由于ujson崩溃,因此对于排序为空白。由于在转换所有键为str之前尝试排序而引发TypeError,因此json为空白。rapidjson为空白,因为它不支持非str键。可以使用pynonstr脚本重现此问题。

OPT_OMIT_MICROSECONDS

不要序列化datetime.datetimedatetime.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"'
OPT_PASSTHROUGH_DATACLASS

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"}'
OPT_PASSTHROUGH_DATETIME

datetime.datetimedatetime.datedatetime.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,则此选项不会影响字典键中的日期时间。

OPT_PASSTHROUGH_SUBCLASS

将内置类型的子类传递给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,则此选项不会影响作为字典键序列化子类。

OPT_SERIALIZE_DATACLASS

这已被弃用,在版本3中没有效果。在版本2中,它用于序列化dataclasses.dataclass实例。更多详情请参阅dataclass

OPT_SERIALIZE_NUMPY

序列化numpy.ndarray实例。更多详情请参阅numpy

OPT_SERIALIZE_UUID

这已被弃用,在版本3中没有效果。在版本2中,它用于序列化uuid.UUID实例。更多详情请参阅UUID

OPT_SORT_KEYS

按排序顺序序列化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相比
orjson 0.32 0.54 1
ujson 1.6 2.07 3.8
rapidjson 1.12 1.65 3.1
simplejson 2.25 3.13 5.8
json 1.78 2.32 4.3

可以使用pysort脚本重现此基准测试。

排序不是排序/区域设置的感知。

>>> import orjson
>>> orjson.dumps({"a": 1, "ä": 2, "A": 3}, option=orjson.OPT_SORT_KEYS)
b'{"A":3,"a":1,"\xc3\xa4":2}'

这是与标准库、rapidjson、simplejson和ujson相同的排序行为。

dataclass 也可以序列化为映射,但这不会对它们产生影响。

OPT_STRICT_INTEGER

强制整数限制为53位。默认情况下,整数限制为64位,与Python标准库相同。更多信息请参见 int

OPT_UTC_Z

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。这是在无需首先通过 loads() 反序列化为Python对象的情况下,从缓存、JSONB字段或单独序列化的对象中包含JSON blob的有效方式。

>>> 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重写为紧凑格式。

输入必须是 bytesstr,并作为位置参数给出。

如果给出的是 str 且输入不是有效的UTF-8,则会引发 orjson.JSONEncodeError。否则,它不会进行验证,并且可以写入无效的JSON。它不会转义字符。实现经过测试,如果给出无效字符串或无效JSON,则不会崩溃。

这与 rapidjson 中的 RawJSON 相似。

反序列化

def loads(__obj: Union[bytes, bytearray, memoryview, str]) -> Any: ...

loads() 将JSON反序列化为Python对象。它反序列化为 dictlistintfloatstrboolNone 对象。

接受 bytesbytearraymemoryviewstr 输入。如果输入存在为 memoryviewbytearraybytes 对象,则建议直接传递这些对象而不是创建不必要的 str 对象。即,使用 orjson.loads(b"{}") 而不是 orjson.loads(b"{}".decode("utf-8"))。这具有更低的内存使用率和更低的延迟。

输入必须是有效的UTF-8。

orjson 在整个过程中维护一个映射键的缓存。这通过避免重复字符串来减少了内存使用量。键的长度必须不超过64字节才能被缓存,存储2048个条目。

在调用期间,全局解释器锁(GIL)被持有。

如果给出无效的类型或无效的JSON,则会引发 JSONDecodeError。这包括如果输入包含 NaNInfinity-Infinity,虽然标准库允许这些,但它们不是有效的JSON。

如果数组或对象的组合递归到1024层深,则会引发 JSONDecodeError

JSONDecodeErrorjson.JSONDecodeErrorValueError 的子类。这是为了与标准库兼容。

类型

数据类

orjson 以原生方式序列化 dataclasses.dataclass 实例。它比其他库快40-50倍,并且避免了与其他库相比序列化 dict 时出现的严重减速。

支持传递所有数据类变体,包括使用 __slots__ 的数据类、冻结数据类、具有可选或默认属性的数据类以及子类。不使用 __slots__ 会有性能优势。

dict (ms) dataclass (ms) 与orjson相比
orjson 1.40 1.60 1
ujson
rapidjson 3.64 68.48 42
simplejson 14.21 92.18 57
json 13.28 94.90 59

这衡量了序列化555KiB的JSON,orjson原生和其他库使用 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 支持具有 tzinfoNonedatetime.timezone.utc、python3.9+ zoneinfo 模块中的时区实例,或来自第三方 pendulumpytzdateutil/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.OPT_PASSTHROUGH_DATETIME

使用“Z”后缀代替“+00:00”来表示UTC(“Zulu”)时间,请使用选项orjson.OPT_UTC_Z

假设没有时区的日期时间都是UTC,请使用选项orjson.OPT_NAIVE_UTC

枚举

orjson原生序列化枚举。选项应用于它们的值。

>>> import enum, datetime, orjson
>>>
class DatetimeEnum(enum.Enum):
    EPOCH = datetime.datetime(1970, 1, 1, 0, 0, 0)
>>> orjson.dumps(DatetimeEnum.EPOCH)
b'"1970-01-01T00:00:00"'
>>> orjson.dumps(DatetimeEnum.EPOCH, option=orjson.OPT_NAIVE_UTC)
b'"1970-01-01T00:00:00+00:00"'

不支持类型的成员的枚举可以使用default进行序列化。

>>> import enum, orjson
>>>
class Custom:
    def __init__(self, val):
        self.val = val

def default(obj):
    if isinstance(obj, Custom):
        return obj.val
    raise TypeError

class CustomEnum(enum.Enum):
    ONE = Custom(1)

>>> orjson.dumps(CustomEnum.ONE, default=default)
b'1'

浮点数

orjson在无精度损失和一致舍入的情况下序列化和反序列化双精度浮点数。

orjson.dumps()将不合规JSON的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]'

整数

orjson默认序列化和反序列化64位整数。支持的范围内是一个有符号64位整数的最小值(-9223372036854775807)到无符号64位整数的最大值(18446744073709551615)。这具有广泛的兼容性,但有些实现只支持53位的整数,例如Web浏览器。对于这些实现,dumps()可以配置为在超过53位范围时引发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

orjson原生序列化numpy.ndarray和单个numpy.float64numpy.float32numpy.float16numpy.half)、numpy.int64numpy.int32numpy.int16numpy.int8numpy.uint64numpy.uint32numpy.uint16numpy.uint8numpy.uintpnumpy.intpnumpy.datetime64numpy.bool实例。

orjson与numpy v1和v2都兼容。

orjson在序列化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]]'

数组必须是一个连续的C数组(C_CONTIGUOUS)和受支持的其中一种数据类型。

注意使用tolist()orjson.dumps(..., option=orjson.OPT_SERIALIZE_NUMPY)序列化numpy.float32之间的差异:tolist()在序列化之前将转换为double,而orjson的本地路径则不会。这可能导致不同的舍入。

numpy.datetime64实例序列化为RFC 3339字符串,日期时间选项会影响它们。

>>> import orjson, numpy
>>> orjson.dumps(
        numpy.datetime64("2021-01-01T00:00:00.172"),
        option=orjson.OPT_SERIALIZE_NUMPY,
)
b'"2021-01-01T00:00:00.172000"'
>>> orjson.dumps(
        numpy.datetime64("2021-01-01T00:00:00.172"),
        option=(
            orjson.OPT_SERIALIZE_NUMPY |
            orjson.OPT_NAIVE_UTC |
            orjson.OPT_OMIT_MICROSECONDS
        ),
)
b'"2021-01-01T00:00:00+00:00"'

如果数组不是一个连续的C数组,包含不受支持的数据类型,或包含使用不受支持表示的numpy.datetime64(例如,皮秒),orjson将回退到default。在default中,可以指定obj.tolist()

如果数组不是本地顺序,例如在低端系统上大端值的数组,将引发orjson.JSONEncodeError

如果数组格式不正确,将引发orjson.JSONEncodeError

这测量了从具有(50000, 100)维度和numpy.float64值的numpy.ndarray序列化92MiB JSON的过程。

延迟(毫秒) RSS差(MiB) 与orjson相比
orjson 194 99 1.0
ujson
rapidjson 3,048 309 15.7
simplejson 3,023 297 15.6
json 3,133 297 16.1

这测量了从具有(100000, 100)维度和numpy.int32值的numpy.ndarray序列化100MiB JSON的过程。

延迟(毫秒) RSS差(MiB) 与orjson相比
orjson 178 115 1.0
ujson
rapidjson 1,512 551 8.5
simplejson 1,606 504 9.0
json 1,506 503 8.4

这测量了从具有(100000, 200)维度和numpy.bool值的numpy.ndarray序列化105MiB JSON的过程。

延迟(毫秒) RSS差(MiB) 与orjson相比
orjson 157 120 1.0
ujson
rapidjson 710 327 4.5
simplejson 931 398 5.9
json 996 400 6.3

在这些基准测试中,orjson原生序列化,ujson为空,因为它不支持默认参数,其他库通过default序列化ndarray.tolist()。RSS列测量序列化期间的峰值内存使用。这可以使用pynumpy脚本重现。

orjson没有安装或编译对numpy的依赖。实现是独立的,使用PyArrayInterface读取numpy.ndarray

字符串

orjson对UTF-8的符合性很严格。这比标准库的json模块更严格,它将序列化和反序列化无效UTF-8的UTF-16代理,例如"\ud800"。

如果orjson.dumps()接收到不包含有效UTF-8的str,将引发orjson.JSONEncodeError。如果loads()接收到无效UTF-8,将引发orjson.JSONDecodeError

orjson和rapidjson是唯一在坏输入上一致引发错误的比较JSON库。

>>> import orjson, ujson, rapidjson, json
>>> orjson.dumps('\ud800')
JSONEncodeError: str is not valid UTF-8: surrogates not allowed
>>> ujson.dumps('\ud800')
UnicodeEncodeError: 'utf-8' codec ...
>>> rapidjson.dumps('\ud800')
UnicodeEncodeError: 'utf-8' codec ...
>>> json.dumps('\ud800')
'"\\ud800"'
>>> orjson.loads('"\\ud800"')
JSONDecodeError: unexpected end of hex escape at line 1 column 8: line 1 column 1 (char 0)
>>> ujson.loads('"\\ud800"')
''
>>> rapidjson.loads('"\\ud800"')
ValueError: Parse error at offset 1: The surrogate pair in string is invalid.
>>> json.loads('"\\ud800"')
'\ud800'

为了尽可能正确地反序列化无效输入,首先使用errors参数的replacelossy选项对bytes进行解码。

>>> import orjson
>>> orjson.loads(b'"\xed\xa0\x80"')
JSONDecodeError: str is not valid UTF-8: surrogates not allowed
>>> orjson.loads(b'"\xed\xa0\x80"'.decode("utf-8", "replace"))
'���'

UUID

orjson将uuid.UUID实例序列化为RFC 4122格式,例如,“f81d4fae-7dec-11d0-a765-00a0c91e6bf6”。

>>> 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"'

测试

该库具有全面的测试。它对JSONTestSuitenativejson-benchmark仓库中的固定值进行了测试。它被测试为不会因Big List of Naughty Strings而崩溃。它被测试为不会泄漏内存。它被测试为不会因无效的UTF-8而崩溃或不接受。它还有集成测试,用于在Web服务器(使用多进程/分叉工作进程的gunicorn)和多线程时使用库。它还使用了ultrajson库的一些测试。

orjson是所比较库中最正确的。此图显示了每个库如何处理来自JSONTestSuitenativejson-benchmark测试的342个JSON固定值。

不拒绝无效的JSON文档 不反序列化有效的JSON文档
orjson 0 0
ujson 31 0
rapidjson 6 0
simplejson 10 0
json 17 0

这表明所有库都能反序列化有效的JSON,但只有orjson正确地拒绝了给定的无效JSON固定值。错误大部分是由于接受无效的字符串和数字。

可以使用pycorrectness脚本来重现上面的图。

性能

orjson的序列化和反序列化性能优于ultrajson、rapidjson、simplejson和json。基准测试是在真实数据的固定值上进行的

  • twitter.json,631.5KiB,Twitter上搜索“一”的结果,包含CJK字符串、字符串字典和字典数组,缩进。

  • github.json,55.8KiB,GitHub活动源,包含字符串字典和字典数组,未缩进。

  • citm_catalog.json,1.7MiB,音乐会数据,包含嵌套的字符串字典和整数数组,缩进。

  • canada.json,2.2MiB,加拿大边界的GeoJSON格式坐标,包含浮点数和数组,缩进。

延迟

Serialization

Deserialization

twitter.json序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 0.1 8377 1
ujson 0.9 1088 7.3
rapidjson 0.8 1228 6.8
simplejson 1.9 531 15.6
json 1.4 744 11.3

twitter.json反序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 0.6 1811 1
ujson 1.2 814 2.1
rapidjson 2.1 476 3.8
simplejson 1.6 626 3
json 1.8 557 3.3

github.json序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 0.01 104424 1
ujson 0.09 10594 9.8
rapidjson 0.07 13667 7.6
simplejson 0.2 5051 20.6
json 0.14 7133 14.6

github.json反序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 0.05 20069 1
ujson 0.11 8913 2.3
rapidjson 0.13 8077 2.6
simplejson 0.11 9342 2.1
json 0.11 9291 2.2

citm_catalog.json序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 0.3 3757 1
ujson 1.7 598 6.3
rapidjson 1.3 768 4.9
simplejson 8.3 120 31.1
json 3 331 11.3

citm_catalog.json反序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 1.4 730 1
ujson 2.6 384 1.9
rapidjson 4 246 3
simplejson 3.7 271 2.7
json 3.7 267 2.7

canada.json序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 2.4 410 1
ujson 9.6 104 3.9
rapidjson 28.7 34 11.8
simplejson 49.3 20 20.3
json 30.6 32 12.6

canada.json反序列化

中值延迟(毫秒) 每秒操作数 相对(延迟)
orjson 3 336 1
ujson 7.1 141 2.4
rapidjson 20.1 49 6.7
simplejson 16.8 59 5.6
json 18.2 55 6.1

内存

由于解析时使用持久缓冲区,orjson 3.7.0的基线内存使用量高于其他库。反序列化时的增量内存使用量与标准库和其他第三方库相似。

第一列测量在导入库并读取固定值后的RSS,第二列测量在固定值上反复调用loads()后的RSS增加。

twitter.json

导入,read() RSS(MiB) loads() RSS增加(MiB)
orjson 15.7 3.4
ujson 16.4 3.4
rapidjson 16.6 4.4
simplejson 14.5 1.8
json 13.9 1.8

github.json

导入,read() RSS(MiB) loads() RSS增加(MiB)
orjson 15.2 0.4
ujson 15.4 0.4
rapidjson 15.7 0.5
simplejson 13.7 0.2
json 13.3 0.1

citm_catalog.json

导入,read() RSS(MiB) loads() RSS增加(MiB)
orjson 16.8 10.1
ujson 17.3 10.2
rapidjson 17.6 28.7
simplejson 15.8 30.1
json 14.8 20.5

canada.json

导入,read() RSS(MiB) loads() RSS增加(MiB)
orjson 17.2 22.1
ujson 17.4 18.3
rapidjson 18 23.5
simplejson 15.7 21.4
json 15.4 20.4

重现

上述测量是在Linux(amd64)上的Python 3.11.9和orjson 3.10.6、ujson 5.10.0、python-rapidson 1.18和simplejson 3.19.2上进行的。

可以使用pybenchgraph脚本来重现延迟结果。可以使用pymem脚本来重现内存结果。

问题

为什么我无法从PyPI安装它?

可能需要将pip升级到20.3或更高版本,以支持最新的manylinux_x_y或universal2 wheel格式。

“Cargo,Rust包管理器,未安装或不在PATH中。”

当PyPI上没有针对您的平台的二进制轮子(如manylinux)时,会出现这种情况。您可以通过rustup或包管理器安装Rust,然后它会进行编译。

它能否反序列化为dataclasses、UUIDs、十进制数等,或者支持object_hook吗?

不,这需要一个指定预期类型和处理错误等的模式。这可以通过比这更高一级的数据验证库来解决。

它能否序列化为str

不,序列化的blob应该使用bytes类型。

打包

要打包或json,至少需要Rust 1.72和maturin构建工具。推荐的构建命令是

maturin build --release --strip

它还受益于有一个C构建环境来编译更快的反序列化后端。请参阅该项目使用clang和LTO的manylinux_2_28构建示例。

项目自己的CI测试针对nightly-2024-08-05和稳定版1.72。明智的做法是将nightly版本锁定,因为该渠道可能会引入破坏性更改。

orjson在Linux上针对amd64、aarch64、arm7、ppc64le和s390x进行了测试。在macOS上,它针对aarch64或amd64进行了测试,并根据版本进行交叉编译。对于Windows,它针对amd64和i686进行了测试。

除了libc之外,没有其他运行时依赖项。

PyPI上的源分布包含所有依赖项的源代码,并且可以在没有网络访问的情况下构建。可以从https://files.pythonhosted.org/packages/source/o/orjson/orjson-${version}.tar.gz下载文件。

orjson的测试包含在PyPI上的源分布中。运行测试的要求在test/requirements.txt中指定。测试应在构建过程中运行。可以使用pytest -q test运行。

许可证

orjson由ijl编写,邮箱:[email protected],版权所有 2018 - 2024,您可以选择Apache 2许可证或MIT许可证。

项目详情


发布历史 发布通知 | RSS源

下载文件

下载适用于您平台的项目文件。如果您不确定该选择哪一个,请了解有关安装包的更多信息。

源分布

orjson-3.10.7.tar.gz (5.1 MB 查看哈希值)

上传时间:

构建分布

orjson-3.10.7-cp313-none-win_amd64.whl (137.1 kB 查看哈希值)

上传时间: CPython 3.13 Windows x86-64

orjson-3.10.7-cp313-none-win32.whl (143.1 kB 查看哈希值)

上传时间: CPython 3.13 Windows x86

orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl (167.9 kB 查看哈希值)

上传时间: CPython 3.13 musllinux: musl 1.2+ x86-64

orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl (169.9 kB 查看哈希值)

上传时间: CPython 3.13 musllinux: musl 1.2+ ARM64

orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (142.0 kB 查看哈希值)

上传时间: CPython 3.13 manylinux: glibc 2.17+ x86-64

orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl (251.3 kB 查看哈希值)

上传于 CPython 3.13 macOS 10.15+ universal2 (ARM64, x86-64) macOS 10.15+ x86-64 macOS 11.0+ ARM64

orjson-3.10.7-cp312-none-win_amd64.whl (137.3 kB 查看哈希值)

上传于 CPython 3.12 Windows x86-64

orjson-3.10.7-cp312-none-win32.whl (143.1 kB 查看哈希值)

上传于 CPython 3.12 Windows x86

orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl (168.0 kB 查看哈希值)

上传于 CPython 3.12 musllinux: musl 1.2+ x86-64

orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl (169.9 kB 查看哈希值)

上传于 CPython 3.12 musllinux: musl 1.2+ ARM64

orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (142.0 kB 查看哈希值)

上传于 CPython 3.12 manylinux: glibc 2.17+ x86-64

orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (164.0 kB 查看哈希值)

上传于 CPython 3.12 manylinux: glibc 2.17+ s390x

orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (153.0 kB 查看哈希值)

上传于 CPython 3.12 manylinux: glibc 2.17+ ppc64le

orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (147.4 kB 查看哈希值)

上传于 CPython 3.12 manylinux: glibc 2.17+ ARMv7l

orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (147.9 kB 查看哈希值)

上传于 CPython 3.12 manylinux: glibc 2.17+ ARM64

orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl (251.4 kB 查看哈希值)

上传于 CPython 3.12 macOS 10.15+ universal2 (ARM64, x86-64) macOS 10.15+ x86-64 macOS 11.0+ ARM64

orjson-3.10.7-cp311-none-win_amd64.whl (137.3 kB 查看哈希值)

上传于 CPython 3.11 Windows x86-64

orjson-3.10.7-cp311-none-win32.whl (143.0 kB 查看哈希值)

上传于 CPython 3.11 Windows x86

orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl (167.8 kB 查看哈希值)

上传于 CPython 3.11 musllinux: musl 1.2+ x86-64

orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl (170.2 kB 查看哈希值)

上传于 CPython 3.11 musllinux: musl 1.2+ ARM64

orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (141.9 kB 查看哈希值)

上传于 CPython 3.11 manylinux: glibc 2.17+ x86-64

orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (164.0 kB 查看哈希值)

上传于 CPython 3.11 manylinux: glibc 2.17+ s390x

orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (153.0 kB 查看哈希值)

上传于 CPython 3.11 manylinux: glibc 2.17+ ppc64le

orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (147.3 kB 查看哈希值)

上传于 CPython 3.11 manylinux: glibc 2.17+ ARMv7l

orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (148.1 kB 查看哈希值)

上传于 CPython 3.11 manylinux: glibc 2.17+ ARM64

orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl (251.3 kB 查看哈希值)

上传于 CPython 3.11 macOS 10.15+ universal2 (ARM64, x86-64) macOS 10.15+ x86-64 macOS 11.0+ ARM64

orjson-3.10.7-cp310-none-win_amd64.whl (137.3 kB 查看哈希)

上传于 CPython 3.10 Windows x86-64

orjson-3.10.7-cp310-none-win32.whl (143.0 kB 查看哈希)

上传于 CPython 3.10 Windows x86

orjson-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl (167.8 kB 查看哈希)

上传于 CPython 3.10 musllinux: musl 1.2+ x86-64

orjson-3.10.7-cp310-cp310-musllinux_1_2_aarch64.whl (170.2 kB 查看哈希)

上传于 CPython 3.10 musllinux: musl 1.2+ ARM64

orjson-3.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (141.9 kB 查看哈希)

上传于 CPython 3.10 manylinux: glibc 2.17+ x86-64

orjson-3.10.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (164.0 kB 查看哈希)

上传于 CPython 3.10 manylinux: glibc 2.17+ s390x

orjson-3.10.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (153.0 kB 查看哈希)

上传于 CPython 3.10 manylinux: glibc 2.17+ ppc64le

orjson-3.10.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (147.3 kB 查看哈希)

上传于 CPython 3.10 manylinux: glibc 2.17+ ARMv7l

orjson-3.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (148.1 kB 查看哈希)

上传于 CPython 3.10 manylinux: glibc 2.17+ ARM64

orjson-3.10.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl (251.3 kB 查看哈希)

上传于 CPython 3.10 macOS 10.15+ universal2 (ARM64, x86-64) macOS 10.15+ x86-64 macOS 11.0+ ARM64

orjson-3.10.7-cp39-none-win_amd64.whl (137.1 kB 查看哈希值)

上传于 CPython 3.9 Windows x86-64

orjson-3.10.7-cp39-none-win32.whl (142.9 kB 查看哈希值)

上传于 CPython 3.9 Windows x86

orjson-3.10.7-cp39-cp39-musllinux_1_2_x86_64.whl (167.6 kB 查看哈希值)

上传于 CPython 3.9 musllinux: musl 1.2+ x86-64

orjson-3.10.7-cp39-cp39-musllinux_1_2_aarch64.whl (170.0 kB 查看哈希值)

上传于 CPython 3.9 musllinux: musl 1.2+ ARM64

orjson-3.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (141.7 kB 查看哈希值)

上传于 CPython 3.9 manylinux: glibc 2.17+ x86-64

orjson-3.10.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl (163.7 kB 查看哈希值)

上传于 CPython 3.9 manylinux: glibc 2.17+ s390x

orjson-3.10.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (152.7 kB 查看哈希值)

上传于 CPython 3.9 manylinux: glibc 2.17+ ppc64le

orjson-3.10.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (147.1 kB 查看哈希值)

上传于 CPython 3.9 manylinux: glibc 2.17+ ARMv7l

orjson-3.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (147.9 kB 查看哈希值)

上传于 CPython 3.9 manylinux: glibc 2.17+ ARM64

orjson-3.10.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl (251.3 kB 查看哈希值)

上传于 CPython 3.9 macOS 10.15+ universal2 (ARM64, x86-64) macOS 10.15+ x86-64 macOS 11.0+ ARM64

orjson-3.10.7-cp38-none-win_amd64.whl (137.0 kB 查看哈希值)

上传于 CPython 3.8 Windows x86-64

orjson-3.10.7-cp38-none-win32.whl (142.7 kB 查看哈希值)

上传于 CPython 3.8 Windows x86

orjson-3.10.7-cp38-cp38-musllinux_1_2_x86_64.whl (167.4 kB 查看哈希值)

上传于 CPython 3.8 musllinux: musl 1.2+ x86-64

orjson-3.10.7-cp38-cp38-musllinux_1_2_aarch64.whl (169.7 kB 查看哈希值)

上传于 CPython 3.8 musllinux: musl 1.2+ ARM64

orjson-3.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (141.5 kB 查看哈希值)

上传于 CPython 3.8 manylinux: glibc 2.17+ x86-64

orjson-3.10.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl (163.5 kB 查看哈希值)

上传于 CPython 3.8 manylinux: glibc 2.17+ s390x

orjson-3.10.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (152.5 kB 查看哈希值)

上传于 CPython 3.8 manylinux: glibc 2.17+ ppc64le

orjson-3.10.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (146.9 kB 查看哈希值)

上传于 CPython 3.8 manylinux: glibc 2.17+ ARMv7l

orjson-3.10.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (147.8 kB 查看哈希值)

上传于 CPython 3.8 manylinux: glibc 2.17+ ARM64

orjson-3.10.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl (251.1 kB 查看哈希值)

上传于 CPython 3.8 macOS 10.15+ universal2 (ARM64, x86-64) macOS 10.15+ x86-64 macOS 11.0+ ARM64

由以下支持