Skip to content

orjson

orjson是 Python 下的一个 JSON 库,与其他 Pyhton JSON 库相比有以下几个重要特性:

  • 支持对 dataclass、datetime、numpy 和 UUID 的序列化
  • 支持序列化 bytes
  • 序列化和反序列化的速度更快
  • 支持使用 default 钩子来序列化任何类型
  • 严格遵循 JSON 规范,例如不支持 NaN/Infinity/-Infinity 以及严格遵循 utf-8
  • (缺点)没有提供 load()dump() 类面向 file-like object 的接口

安装

Bash
pip install orjson

conda install orjson

快速入门

它实现了类似标准库的 dumps 序列化(编码器) 和 loads 反序列化(解码器):

Python
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]]}

序列化

使用 dumps 函数来执行序列化,它默认支持 str、dict、list、tuple、int、float、bool、None、dataclasses.dataclassstyping.TypedDictdatetime.datetimedatetime.datedatetime.timeuuid.UUIDnumpy.ndarrayorjson.Fragment 类型数据。

可以通过 option 参数来控制序列化的行为, 以及通过 default 参数来为任意类型添加序列化器。

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

Tips

最需要注意的就是返回值是 bytes

default

如果想要序列化任意类型,尤其是 orjson 不支持的类型可以使用 default 来实现,他接受一个可执行对象(函数、lambda或可调用类实例):

Python
>>> 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

注意如果想要实现无法处理类型引发异常,必须手动 raise,默认是返回 None:

Python
>>> 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

通过指定 option 参数来修改数据的序列化方式,他的参数都是一个整数常量,可能值包括:

  • orjson.OPT_APPEND_NEWLINE: 将 \n 追加到输出中
Python
>>> import orjson
>>> orjson.dumps([])
b"[]"
>>> orjson.dumps([], option=orjson.OPT_APPEND_NEWLINE)
b"[]\n"
  • orjson.OPT_INDENT_2: 更漂亮的打印输出,缩进两个空格
Python
>>> 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}'
  • orjson.OPT_NAIVE_UTC: 将 datetime.datetime 对象作为 UTC 进行序列化(如果带有 tzinfo 不受影响)
  • orjson.OPT_PASSTHROUGH_DATETIME: 将 datetime 相关的序列化委托为 default:
Python
>>> 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"}'

反序列化

反序列化使用 loads 函数执行,它能够将 JSON 反序列化为 Python 对象,默认支持反序列化为 dict、list、int、float、str、bool 和 None 对象。

他支持 Bytes、ByteArray、MemoryView 和 str 作为输入,但是需要注意输入必须是 utf-8 编码:

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