# orjson
orjson is a fast, correct JSON library for Python. It
[benchmarks](https://github.com/ijl/orjson#performance) as the fastest Python
library for JSON and is more correct than the standard json library or other
third-party libraries. It serializes
[dataclass](https://github.com/ijl/orjson#dataclass),
[datetime](https://github.com/ijl/orjson#datetime),
[numpy](https://github.com/ijl/orjson#numpy), and
[UUID](https://github.com/ijl/orjson#uuid) instances natively.
Its features and drawbacks compared to other Python JSON libraries:
* serializes `dataclass` instances 40-50x as fast as other libraries
* serializes `datetime`, `date`, and `time` instances to RFC 3339 format,
e.g., "1970-01-01T00:00:00+00:00"
* serializes `numpy.ndarray` instances 4-12x as fast with 0.3x the memory
usage of other libraries
* pretty prints 10x to 20x as fast as the standard library
* serializes to `bytes` rather than `str`, i.e., is not a drop-in replacement
* serializes `str` without escaping unicode to ASCII, e.g., "好" rather than
"\\\u597d"
* serializes `float` 10x as fast and deserializes twice as fast as other
libraries
* serializes subclasses of `str`, `int`, `list`, and `dict` natively,
requiring `default` to specify how to serialize others
* serializes arbitrary types using a `default` hook
* has strict UTF-8 conformance, more correct than the standard library
* has strict JSON conformance in not supporting Nan/Infinity/-Infinity
* has an option for strict JSON conformance on 53-bit integers with default
support for 64-bit
* does not provide `load()` or `dump()` functions for reading from/writing to
file-like objects
orjson supports CPython 3.6, 3.7, 3.8, 3.9, and 3.10. It distributes x86_64/amd64
and aarch64/armv8 wheels for Linux and macOS. It distributes x86_64/amd64 wheels
for Windows. orjson does not support PyPy. Releases follow semantic
versioning and serializing a new object type without an opt-in flag is
considered a breaking change.
orjson is licensed under both the Apache 2.0 and MIT licenses. The
repository and issue tracker is
[github.com/ijl/orjson](https://github.com/ijl/orjson), and patches may be
submitted there. There is a
[CHANGELOG](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
available in the repository.
1. [Usage](https://github.com/ijl/orjson#usage)
1. [Install](https://github.com/ijl/orjson#install)
2. [Quickstart](https://github.com/ijl/orjson#quickstart)
3. [Migrating](https://github.com/ijl/orjson#migrating)
4. [Serialize](https://github.com/ijl/orjson#serialize)
1. [default](https://github.com/ijl/orjson#default)
2. [option](https://github.com/ijl/orjson#option)
5. [Deserialize](https://github.com/ijl/orjson#deserialize)
2. [Types](https://github.com/ijl/orjson#types)
1. [dataclass](https://github.com/ijl/orjson#dataclass)
2. [datetime](https://github.com/ijl/orjson#datetime)
3. [enum](https://github.com/ijl/orjson#enum)
4. [float](https://github.com/ijl/orjson#float)
5. [int](https://github.com/ijl/orjson#int)
6. [numpy](https://github.com/ijl/orjson#numpy)
7. [str](https://github.com/ijl/orjson#str)
8. [uuid](https://github.com/ijl/orjson#uuid)
3. [Testing](https://github.com/ijl/orjson#testing)
4. [Performance](https://github.com/ijl/orjson#performance)
1. [Latency](https://github.com/ijl/orjson#latency)
2. [Memory](https://github.com/ijl/orjson#memory)
3. [Reproducing](https://github.com/ijl/orjson#reproducing)
5. [Questions](https://github.com/ijl/orjson#questions)
6. [Packaging](https://github.com/ijl/orjson#packaging)
7. [License](https://github.com/ijl/orjson#license)
## Usage
### Install
To install a wheel from PyPI:
```sh
pip install --upgrade "pip>=19.3" # manylinux2014 support
pip install --upgrade orjson
```
Notice that Linux environments with a `pip` version shipped in 2018 or earlier
must first upgrade `pip` to support `manylinux2014` wheels.
To build a wheel, see [packaging](https://github.com/ijl/orjson#packaging).
### Quickstart
This is an example of serializing, with options specified, and deserializing:
```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]]}
```
### Migrating
orjson version 3 serializes more types than version 2. Subclasses of `str`,
`int`, `dict`, and `list` are now serialized. This is faster and more similar
to the standard library. It can be disabled with
`orjson.OPT_PASSTHROUGH_SUBCLASS`.`dataclasses.dataclass` instances
are now serialized by default and cannot be customized in a
`default` function unless `option=orjson.OPT_PASSTHROUGH_DATACLASS` is
specified. `uuid.UUID` instances are serialized by default.
For any type that is now serialized,
implementations in a `default` function and options enabling them can be
removed but do not need to be. There was no change in deserialization.
To migrate from the standard library, the largest difference is that
`orjson.dumps` returns `bytes` and `json.dumps` returns a `str`. Users with
`dict` objects using non-`str` keys should specify
`option=orjson.OPT_NON_STR_KEYS`. `sort_keys` is replaced by
`option=orjson.OPT_SORT_KEYS`. `indent` is replaced by
`option=orjson.OPT_INDENT_2` and other levels of indentation are not
supported.
### Serialize
```python
def dumps(
__obj: Any,
default: Optional[Callable[[Any], Any]] = ...,
option: Optional[int] = ...,
) -> bytes: ...
```
`dumps()` serializes Python objects to JSON.
It natively serializes
`str`, `dict`, `list`, `tuple`, `int`, `float`, `bool`,
`dataclasses.dataclass`, `typing.TypedDict`, `datetime.datetime`,
`datetime.date`, `datetime.time`, `uuid.UUID`, `numpy.ndarray`, and
`None` instances. It supports arbitrary types through `default`. It
serializes subclasses of `str`, `int`, `dict`, `list`,
`dataclasses.dataclass`, and `enum.Enum`. It does not serialize subclasses
of `tuple` to avoid serializing `namedtuple` objects as arrays. To avoid
serializing subclasses, specify the option `orjson.OPT_PASSTHROUGH_SUBCLASS`.
The output is a `bytes` object containing UTF-8.
The global interpreter lock (GIL) is held for the duration of the call.
It raises `JSONEncodeError` on an unsupported type. This exception message
describes the invalid object with the error message
`Type is not JSON serializable: ...`. To fix this, specify
[default](https://github.com/ijl/orjson#default).
It raises `JSONEncodeError` on a `str` that contains invalid UTF-8.
It raises `JSONEncodeError` on an integer that exceeds 64 bits by default or,
with `OPT_STRICT_INTEGER`, 53 bits.
It raises `JSONEncodeError` if a `dict` has a key of a type other than `str`,
unless `OPT_NON_STR_KEYS` is specified.
It raises `JSONEncodeError` if the output of `default` recurses to handling by
`default` more than 254 levels deep.
It raises `JSONEncodeError` on circular references.
It raises `JSONEncodeError` if a `tzinfo` on a datetime object is
unsupported.
`JSONEncodeError` is a subclass of `TypeError`. This is for compatibility
with the standard library.
#### default
To serialize a subclass or arbitrary types, specify `default` as a
callable that returns a supported type. `default` may be a function,
lambda, or callable class instance. To specify that a type was not
handled by `default`, raise an exception such as `TypeError`.
```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 seri