alltools.one
JSON
2025-07-09
10 min
alltools.one Team
JSONSchemaValidationAPIData Quality

JSON Schema 驗證:權威指南

JSON Schema 是一套用於註解和驗證 JSON 文件的詞彙規範。它為你的資料提供了一份契約——定義資料應該具備什麼形狀、接受什麼型別,以及哪些欄位是必填的。如果你的工作涉及 API、設定檔或任何結構化資料,JSON Schema 是你不可或缺的利器。

為什麼要使用 JSON Schema?

沒有驗證的 JSON 資料就像一張萬用牌。你可能收到一個字串格式的 age 欄位、缺少的 email,或格式錯誤的日期。JSON Schema 在邊界處攔截這些問題,防止錯誤資料在系統中擴散。

主要優勢

  • API 契約強制執行:自動驗證請求和回應內容
  • 文件化:Schema 本身就是資料結構的活文件
  • 程式碼產生:工具可以從 JSON Schema 產生型別、表單和資料庫結構
  • 測試:驗證測試資料和模擬資料是否符合 Schema

基本 Schema 結構

每個 JSON Schema 都以幾個標準屬性開始:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/user.schema.json",
  "title": "User",
  "description": "A registered user in the system",
  "type": "object",
  "properties": {
    "id": { "type": "integer", "minimum": 1 },
    "name": { "type": "string", "minLength": 1, "maxLength": 100 },
    "email": { "type": "string", "format": "email" },
    "age": { "type": "integer", "minimum": 0, "maximum": 150 }
  },
  "required": ["id", "name", "email"]
}

使用我們的 JSON 格式化工具 美化你的 Schema,以便在分享給團隊前提高可讀性。

型別約束

JSON Schema 支援六種基本型別:

型別說明範例
string文字資料"hello"
number任何數值3.14
integer僅限整數42
boolean布林值true
array有序列表[1, 2, 3]
object鍵值對{"key": "value"}
null空值null

字串約束

{
  "type": "string",
  "minLength": 1,
  "maxLength": 255,
  "pattern": "^[A-Za-z0-9]+$",
  "format": "email"
}

內建格式包括:emailuridatedate-timeipv4ipv6uuidhostname

數值約束

{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "exclusiveMinimum": 0,
  "multipleOf": 0.01
}

陣列驗證

陣列可以驗證其項目、長度和唯一性:

{
  "type": "array",
  "items": { "type": "string", "format": "email" },
  "minItems": 1,
  "maxItems": 10,
  "uniqueItems": true
}

對於元組驗證(固定長度陣列,每個位置有特定型別):

{
  "type": "array",
  "prefixItems": [
    { "type": "number" },
    { "type": "string" },
    { "type": "boolean" }
  ],
  "items": false
}

物件驗證

物件支援屬性驗證、必填欄位和額外屬性控制:

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "role": { "enum": ["admin", "editor", "viewer"] }
  },
  "required": ["name", "role"],
  "additionalProperties": false
}

additionalProperties 設為 false 是嚴格模式,會拒絕 Schema 中未定義的任何屬性。這對 API 特別有用,可以捕捉欄位名稱的拼寫錯誤。

組合關鍵字

JSON Schema 支援使用邏輯運算子組合 Schema:

allOf(AND)

資料必須對所有子 Schema 有效:

{
  "allOf": [
    { "$ref": "#/$defs/baseUser" },
    { "properties": { "role": { "const": "admin" } } }
  ]
}

oneOf(XOR)

資料必須恰好對一個子 Schema 有效:

{
  "oneOf": [
    { "properties": { "type": { "const": "email" }, "email": { "type": "string" } } },
    { "properties": { "type": { "const": "phone" }, "phone": { "type": "string" } } }
  ]
}

anyOf(OR)

資料必須至少對一個子 Schema 有效。

條件驗證

if/then/else 關鍵字實現條件驗證:

{
  "type": "object",
  "properties": {
    "country": { "type": "string" },
    "postalCode": { "type": "string" }
  },
  "if": {
    "properties": { "country": { "const": "US" } }
  },
  "then": {
    "properties": { "postalCode": { "pattern": "^[0-9]{5}(-[0-9]{4})?$" } }
  },
  "else": {
    "properties": { "postalCode": { "pattern": "^[A-Z0-9 -]+$" } }
  }
}

參考與重用

使用 $ref 參考可重用的定義:

{
  "$defs": {
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "country": { "type": "string" }
      },
      "required": ["street", "city", "country"]
    }
  },
  "type": "object",
  "properties": {
    "billingAddress": { "$ref": "#/$defs/address" },
    "shippingAddress": { "$ref": "#/$defs/address" }
  }
}

實際驗證

JavaScript (Ajv)

const Ajv = require('ajv');
const ajv = new Ajv();

const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) console.log(validate.errors);

Python (jsonschema)

from jsonschema import validate, ValidationError

try:
    validate(instance=data, schema=schema)
except ValidationError as e:
    print(f"Validation error: {e.message}")

如需在不設定開發環境的情況下快速驗證,可以將你的 JSON 和 Schema 貼到我們的 JSON 驗證工具 中。

實際範例:API 回應 Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "status": { "enum": ["success", "error"] },
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "createdAt": { "type": "string", "format": "date-time" }
        },
        "required": ["id", "name"]
      }
    },
    "pagination": {
      "type": "object",
      "properties": {
        "page": { "type": "integer", "minimum": 1 },
        "perPage": { "type": "integer", "minimum": 1, "maximum": 100 },
        "total": { "type": "integer", "minimum": 0 }
      }
    }
  },
  "required": ["status", "data"]
}

常見問題

JSON Schema draft-07 和 2020-12 有什麼差別?

Draft 2020-12 引入了多項改進:prefixItems 取代了 items 的元組形式,$dynamicRef 實現了更靈活的參考機制,詞彙支援允許自訂擴展。新專案建議使用 2020-12。如需與舊工具相容,draft-07 仍然廣泛支援。

JSON Schema 可以驗證字串欄位中的巢狀 JSON 嗎?

不能直接驗證。JSON Schema 驗證的是已解析 JSON 的結構。如果某個欄位包含 JSON 字串,你需要先解析它再單獨驗證。某些驗證器提供自訂格式驗證器來處理此情況,但這不是標準的一部分。

相關資源

Published on 2025-07-09
JSON Schema Validation: The Definitive Guide | alltools.one