|
Voiced by Amazon Polly |
Introduction
If you’ve worked with Python long enough, you’ve almost certainly used the built-in json module. It’s reliable, easy to use, and part of the standard library. But when performance matters, especially in data-heavy applications such as APIs, data pipelines, or real-time systems, the standard JSON module can become a bottleneck.
This is where orjson comes in. orjson is a fast, correct JSON library for Python, written in Rust. It focuses on speed, strict correctness, and modern Python features. In many benchmarks, it’s several times faster than Python’s built-in JSON module while also supporting more advanced data types out of the box.
Pioneers in Cloud Consulting & Migration Services
- Reduced infrastructural costs
- Accelerated application deployment
orjson
At its core, orjson helps you convert Python objects to JSON (serialization) and convert JSON back to Python objects (deserialization). It works just like the built-in JSON module but delivers significantly better performance.
Installation
Installation is straightforward with no extra dependencies:
pip install orjson
Note: It supports Python 3.8 and above on all major platforms.
Basic Usage:
- Serializing Python to JSON
|
1 2 3 4 5 6 7 8 9 10 11 |
import orjson data = {"name": "Esther", "age": 25} json_bytes = orjson.dumps(data) print(json_bytes) Output: b'{"name":"Esther","age":25}' |
Note: Unlike the built-in JSON module, orjson returns bytes, not a string. This is intentional to avoid encoding overhead. If you need a string:
json_str = json_bytes.decode(“utf-8”)
- Deserializing JSON to Python
|
1 2 3 4 5 6 7 8 9 |
json_data = b'{"name":"Esther","age":25}' data = orjson.loads(json_data) print(data) Output: {'name': 'Esther', 'age': 25} |
Note: The loads function accepts both bytes and str inputs.
Key Differences from the Standard JSON Module
- dumps() returns bytes instead of str. This matters when sending responses in web frameworks, writing to files, or logging.
- orjson is significantly faster. Depending on data structure and size, you’ll typically see 2x to 10x improvement in both serialization and deserialization speed.
- orjson is stricter about JSON correctness. For example, orjson.dumps(float(“nan”)) raises an error because NaN is not valid JSON per the RFC specification. This strictness helps avoid subtle bugs when working with APIs.
Working with Common Data Types:
- Datetime Support
Orjson’s biggest advantage is built-in datetime support:
|
1 2 3 4 5 6 7 8 9 |
from datetime import datetime data = {"created_at": datetime.now()} print(orjson.dumps(data)) Output: b'{"created_at":"2026-05-06T12:34:56.789012"}' |
Note: With the standard JSON module, you’d need a custom encoder. orjson handles this automatically, which is a significant productivity win in applications where timestamps are common.
- Dataclass Support
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from dataclasses import dataclass @dataclass class User: name: str age: int user = User("Esther", 25) orjson.dumps(user) |
Note: orjson handles dataclasses natively without additional configuration.
- Numpy Support
For data science workflows, orjson can serialize numpy arrays directly with the appropriate option flag, eliminating the need to convert arrays to lists manually.
Using Options
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
orjson provides options to customize serialization: # Pretty printing orjson.dumps(data, option=orjson.OPT_INDENT_2) # Sort keys for consistent output orjson.dumps(data, option=orjson.OPT_SORT_KEYS) # Combine options with bitwise OR option = orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS orjson.dumps(data, option=option) |
Sorting keys is useful for deterministic output, reliable tests, and improving cache hit rates.
- Error Handling
orjson raises clear exceptions for unsupported types:
|
1 2 3 4 5 6 7 |
try: orjson.dumps(set([1, 2, 3])) except TypeError as e: print("Error:", e) |
For custom objects, use the default parameter:
|
1 2 3 4 5 6 7 8 9 |
def default(obj): if isinstance(obj, set): return list(obj) raise TypeError orjson.dumps({"items": {1, 2, 3}}, default=default) |
Note: This gives you full control over how non-standard types are serialized
Integration with Web Frameworks
Many modern frameworks support orjson directly. FastAPI provides built-in integration:
|
1 2 3 4 5 6 7 8 9 10 11 |
from fastapi import FastAPI from fastapi.responses import ORJSONResponse app = FastAPI(default_response_class=ORJSONResponse) @app.get("/") def read_root(): return {"message": "Hello CloudThat Blog"} |
Note: This uses orjson for all response serialization automatically, providing a free performance boost. For high-traffic APIs, this can meaningfully reduce response times and server resource usage.
Conclusion
orjson is a practical tool for anyone working with JSON in Python where performance matters. It offers significant speed improvements over the standard library while maintaining strict correctness and adding native support for dataclasses, datetime objects, and numpy arrays.
Adoption is easy. Switching from JSON to orjson requires minimal code changes yet delivers noticeable improvements. For production systems, APIs, or data-heavy applications, orjson makes a measurable difference with very little effort.
Drop a query if you have any questions regarding JSON and we will get back to you quickly.
Making IT Networks Enterprise-ready – Cloud Management Services
- Accelerated cloud migration
- End-to-end view of the cloud environment
About CloudThat
FAQs
1. Can I use orjson as a direct replacement for Python's built-in json module?
ANS: – Yes, it works as a near drop-in replacement. The only key difference is that orjson.dumps() returns bytes instead of str, so add .decode(“utf-8”) if you need a string output.
2. Why does orjson return bytes instead of a string?
ANS: – For performance reasons. Most operations, such as HTTP responses and file writes, already require bytes, so skipping the string conversion eliminates unnecessary processing overhead.
3. Does orjson support all Python data types?
ANS: – It supports the most common types, including dicts, lists, strings, numbers, booleans, datetime, uuid, and dataclasses. For unsupported types like sets, use the default parameter to provide a custom conversion function.
WRITTEN BY Esther Jelinal J
Esther Jelinal J is a Research Associate at CloudThat, working as a Full Stack Developer with a strong focus on backend development. She is skilled in technologies such as React.js, Node.js, JavaScript, Python, PostgreSQL, and AWS. With a strong passion for cloud technologies, Esther is growing her expertise as a cloud-native developer. She is enthusiastic about exploring emerging technologies and has the potential to build innovative, scalable solutions.
Login

May 25, 2026
PREV
Comments