Ian Chou's Blog

為什麼 orjson 幾乎是現代 Python Web 專案的預設選擇?

在 Python 生態中,JSON 幾乎無所不在:
API 回傳、設定檔、Log、Streaming、Cache、Message Queue……
問題從來不是「要不要用 JSON」,而是:

用哪一個 JSON library,才能在效能與開發體驗之間取得最佳平衡?

如果你還在 jsonujsonorjson 之間猶豫,這篇文章會給你一個非常明確的答案。


TL;DR(結論先行)

如果你在用 FastAPI / Starlette / SSE / NDJSON
那幾乎沒有理由不用 orjson


一、為什麼效能突然變得這麼重要?

在現代 Web 架構中,JSON 序列化早就不是「可以忽略的成本」:

慢 0.1ms,看起來很小,但乘以 10,000 次就是真實延遲。


二、三大 JSON Library 的核心差異

整體比較表

特性 orjson ujson 標準 json
底層實作 Rust C/C++ Python + C
dumps 回傳 bytes str str
序列化速度 最快
datetime 支援 原生支援
dataclass 支援 原生支援
JSON 規範 嚴格 較寬鬆 嚴格

一句話總結:

orjson 是「效能極限 + 現代 Python 類型友善」的 JSON。


三、orjson 為什麼這麼快?

1️⃣ Rust 的優勢

2️⃣ 關鍵差異:bytes vs str

這是效能差距的核心。

orjson.dumps(data)  # -> bytes
json.dumps(data)    # -> str

在 Web Server 中,流程通常是:

Python Object
 → JSON String
 → UTF-8 encode
 → Bytes
 → Socket

orjson 直接跳過中間那個 String。

FastAPI 為什麼預設推薦 orjson
因為 HTTP Response 最終就是 bytes。


四、開發體驗:orjson 幾乎不用寫樣板程式碼

datetime、dataclass,直接可用

import orjson
from datetime import datetime
from dataclasses import dataclass

@dataclass
class User:
    id: int
    name: str

data = {
    "created_at": datetime.now(),
    "user": User(1, "Alice")
}

print(orjson.dumps(data))

👉 不用 Custom Encoder,不用轉型,不用 try/except

這一點在真實專案中,能省下大量心智負擔。


五、Web API:前端完全不用改

這是很多人第一次聽到 orjson 時最大的疑問:

前端是不是也要裝東西?

答案是:完全不用。

orjson 只是「產生 JSON 的方式不同」,
產物仍然是 100% 標準 JSON。

// React / Next.js
const res = await fetch("/api/user");
const data = await res.json(); // 完全一樣

前端甚至不知道後端換過 JSON library。


六、Streaming / SSE:orjson 的主戰場

在 Streaming 場景中,orjson 的優勢會被放大。

SSE 範例(FastAPI)

import orjson
import asyncio
from fastapi.responses import StreamingResponse

async def event_generator():
    for i in range(5):
        payload = {"token": i, "text": "thinking..."}
        yield b"data: " + orjson.dumps(payload) + b"\n\n"
        await asyncio.sleep(0.5)

@app.get("/stream")
def stream():
    return StreamingResponse(event_generator(), media_type="text/event-stream")

為什麼這樣寫很重要?


七、那 MessagePack 呢?不是更快嗎?

是的,但要看 「誰是資料消費者」

決策矩陣

使用場景 推薦
瀏覽器 / Web API orjson
Backend-to-Backend MessagePack
Redis / Cache MessagePack
Log / Observability orjson
小腳本 標準 json

MessagePack 贏在體積與頻寬,
orjson 贏在 通用性 + 開發效率 + 生態整合


八、唯一要注意的陷阱:BigInt

這不是 orjson 的問題,是 JSON 的天生限制。

{"id": 9223372036854775807}

JavaScript 可能會精度遺失。

👉 解法很簡單:後端轉成字串再送。


九、總結:什麼時候「不該」用 orjson?

只有三種情況:

  1. 極簡腳本(不想 pip install)
  2. 非常舊的 Python 版本
  3. 專案嚴格禁止 native extension

否則:

在 2025 年的 Python Web 專案中,不用 orjson,反而需要理由。


結語

orjson 的成功,不是因為它「比較快一點」,
而是因為它 剛好踩在現代 Python 的所有甜蜜點上

如果你正在做 API、SSE、LLM 應用或任何高頻 JSON 處理,
orjson 當成預設選項,你幾乎不會後悔。