在 Python 中檢查 JSON 結構

在 Python 中檢查 JSON 結構
程式技術

最近在用改寫一個用 Python 寫的小工具,這個工具主要是為了讓某些日常作業可以自動化。程式中有一個部分,是從 AWS Secret Manager 上取得格式為 JSON 的敏感資料,在讀取這個資料之前,會先對資料的結構進行檢查,之前的做法是使用斷定:

data = {
    "username": "Allen",
    "email": "allen@email.com",
}

assert "username" in data, "username missing!"
assert "email" in data, "email missing!"

雖然這個方法也行得通,但如果是較為複雜的資料結構,那我就會有寫不完的斷定了,日後在閱讀上也很不直觀。

此時我想到 Laravel 在測試上有提供一個很方便的語法,可以用來檢查 API 回傳的 JSON 結構。

test('we can get the latest posts', function () {
    Post::factory(6)->create();

    get(route('api.posts'))
        // 斷定 API 回傳的 JSON 結構
        ->assertJsonStructure([
            'data' => [
                '*' => ['id', 'title', 'excerpt', 'created_at', 'updated_at', 'url'],
            ],
        ])
        ->assertSuccessful();
});

這讓我不禁開始想,Python 當中有沒有類似的工具可以用來檢查 JSON 的結構?

簡單的 Google 與詢問 AI 之後,只能說 Python 不愧是全世界最流行的語言之一,我的疑問完全是多餘的,有一個 Python 套件 jsonschema 可以很輕鬆的做到這件事情。

安裝套件

我們可以使用 pip 指令安裝 jsonschema。

pip install jsonschema

# 使用 uv
uv python install 3.14
uv add jsonschema

基本使用方式

jsonschema 的使用方式相當簡單,首先使用 Python 的字典(Dictionary)定義好預期的 JSON 結構後,我們就可以使用 validate() 函式來檢查目標資料的結構是否符合我們定義好的結構。如果未符合,函式就會拋出一個例外。

from jsonschema import validate, ValidationError

# 定義預期的資料結構
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "number"},
    },
}

data = {
    "name": "Allen",
    "age": 30,
}

try:
    # 判斷 data 的結構是否與 schema 的相同
    # 如果與 schema 不同,就會拋出例外
    validate(instance=data, schema=schema)
    print("Validation successful")
except ValidationError as e:
    print(f"Validation failed: {e}")

定義結構

在結構定義中,我們需要先使用 type 定義我們預期的型別,以簡單的字串、數字、列表與物件為例。

# 定義一個字串
schema = {
    "type": "string",
}

data = "allen"
# 定義一個數字
schema = {
    "type": "number",
}

data = 30
# 定義一個列表
schema = {
    "type": "array", 
    "items": { "type": "number" }
}

data = [1, 2, 3, 4]
# 定義一個物件
schema = {
    "type": "object",
    "properties": {
        "username": { "type": "string" }
        "age": { "type": "number" } 
    }
}

data = {
    "username": "allen"
    "age": 30
}

jsonschema 提供豐富的選項來定義 JSON 結構。除了判斷型別之外,我們還可以檢查數字的大小以及字串的長度,甚至可以透過正則表達式來檢查字串的格式。

schema = {
    "type": "object",
    "properties": {
        "username": {"type": "string", "minLength": 3, "maxLength": 20},
        "email": {"type": "string", "pattern": r"^\S+@\S+\.\S+$"},
        "age": {"type": "number", "minimum": 0, "maximum": 120},
    },
}

如果是列表型別,也可以檢查列表的長度與是否包含重複的資料。

schema = {
    "type": "array",
    "items": {"type": "number"},
    "minItems": 1,
    "maxItems": 10,
    "uniqueItems": True,
}

需要注意的是,資料結構的鍵值(Key)預設是可選的,如果我們希望這個鍵值是必要的,就需要在 required 中標註。

schema = {
    "type": "object",
    "properties": {
        "username": {"type": "string", "minLength": 3, "maxLength": 20},
        "email": {"type": "string", "pattern": r"^\S+@\S+\.\S+$"},
        "age": {"type": "number", "minimum": 0, "maximum": 120},
    },
    # username 與 email 一定要存在
    "required": ["username", "email"]
}

結合前面的例子,我們就可以來定義較為複雜,甚至是多階層的資料結構。

schema = {
    "type": "object",
    "properties": {
        "id": {"type": "number"},
        "user": {
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "email": {"type": "string"}
            },
            "required": ["name"]
        }
    },
    "required": ["id", "user"]
}

如果你跟我一樣還在使用很多斷定來檢查資料結構,不妨考慮看看 jsonschema 這個套件!不只易用,也能增加程式碼的可讀性。

參考資料

Allen
written by
Allen

持續努力中的後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

則留言
Allen Allen (已編輯)

最近開始在自己的 Python 專案中陸續使用 jsonschema,誠心推薦。

顯示更多留言
新增留言
訪客 2026 年 01 月 23 日