← 全部文章

如何驗證 JSON:語法與 schema 驗證

用 JSON.parse、Python 的 json.loads、jq 或瀏覽器驗證 JSON 語法 —— 並學會用 JSON Schema 檢查結構與型別。

校驗 JSON 指的是確認一段字串既在語法上正確(符合 JSON 文法),又(可選地)在結構上正確(與你的應用所期望的形狀一致)。本指南講解如何在 JavaScript、Python、命令列以及瀏覽器中校驗 JSON —— 並解釋語法校驗與 Schema 校驗之間至關重要的差別。

JSON 校驗的兩種

校驗任何東西之前,先想清楚你真正問的是哪個問題:

  • 語法校驗 —— 「這到底是不是合法的 JSON?」按 JSON 文法檢查引號、逗號、括號與值型別。JSON.parse() 做的就是這件事。
  • Schema 校驗 —— 「這份 JSON 是不是有正確的欄位、型別與約束?」會檢查 id 是整數、email 必須存在等等。需要 JSON Schema 以及 Ajv 之類的校驗器。

多數「validate JSON」的搜尋指的就是語法校驗 —— 我們從這裡開始。

在 JavaScript 中校驗 JSON

最簡單也最可靠的語法檢查就是嘗試 parse 並捕獲例外。JSON.parse() 在任何無效輸入上都會丟出 SyntaxError

function isValidJson(text) {
  try {
    JSON.parse(text);
    return true;
  } catch {
    return false;
  }
}

isValidJson('{"name":"Ada"}');  // true
isValidJson("{'name':'Ada'}");  // false —— 單引號
isValidJson('{"a":1,}');        // false —— 尾隨逗號

如果你需要知道字串為何無效的具體原因,就把錯誤訊息保留下來 —— 裡面通常會有出錯位置:

function validateJson(text) {
  try {
    return { valid: true, value: JSON.parse(text) };
  } catch (err) {
    return { valid: false, error: err.message };
  }
}

validateJson('{"a":1,}');
// { valid: false, error: "Expected double-quoted property name in JSON at position 7" }

不要用正規表示式校驗 JSON。JSON 是遞迴文法,正規表示式無法正確校驗 —— JSON.parse() 才是正規的校驗器,每個 JavaScript 執行時都內建了。

在 Python 中校驗 JSON

Python 的 json.loads() 在無效輸入上會丟出 json.JSONDecodeError,帶有精確的行列號:

import json

def is_valid_json(text):
    try:
        json.loads(text)
        return True
    except json.JSONDecodeError as e:
        print(f"Invalid JSON: {e.msg} at line {e.lineno} column {e.colno}")
        return False

is_valid_json('{"name": "Ada"}')   # True
is_valid_json('{"name": "Ada",}')  # False —— 尾隨逗號

在命令列校驗 JSON 檔案

使用 jq

jq 在輸入不是合法 JSON 時會以非零狀態結束,因此非常適合腳本與 CI:

# 合法時不列印且以 0 結束;不合法時列印錯誤並以非零結束
jq empty data.json && echo "valid" || echo "invalid"

使用 Python(不需安裝)

python3 -m json.tool data.json > /dev/null && echo "valid"

在 CI 管線中

把儲存庫裡每個 JSON 檔案都做一次 pre-commit 或 CI 校驗,讓畸形的設定永遠到不了生產環境:

# 任何 .json 不合法時讓建置失敗
find . -name '*.json' -not -path './node_modules/*' \
  -exec sh -c 'jq empty "$1" || exit 255' _ {} \;

在瀏覽器中校驗 JSON

想快速查一下、不寫程式,把 JSON 貼進 fixjson 的 JSON 校驗器。它會隨著你的輸入即時回報語法錯誤的精確行列位置,並完全在本地執行 —— 不會有資料傳到伺服器,因此面對敏感負載也安全。如果 JSON 已經損壞,你想直接修而不只是標出問題,JSON Fix 會自動修正常見錯誤。

不只語法:用 JSON Schema 校驗結構

語法上合法的 JSON 對你的應用而言可能仍是錯的 —— 必填欄位缺失、本該是數字的地方是字串、數值超出範圍。要強制結構,請用 JSON Schema 描述期望的形狀,再用 Ajv(JavaScript)或 jsonschema 函式庫(Python)來校驗:

import Ajv from 'ajv';

const ajv = new Ajv();
const validate = ajv.compile({
  type: 'object',
  required: ['id', 'email'],
  properties: {
    id:    { type: 'integer' },
    email: { type: 'string' },
  },
});

validate({ id: 42, email: 'a@b.com' }); // true
validate({ id: '42' });                 // false —— 型別錯且缺 email
// validate.errors 包含詳細原因

命令列 Schema 校驗

在 CI 中對照 schema 校驗 JSON,兩個 CLI 就足以涵蓋多數需求:

# Python —— 裝一次即可
pip install jsonschema
jsonschema --instance data.json schema.json && echo OK

# Node —— Ajv 的 CLI
npm i -g ajv-cli ajv-formats
ajv validate -c ajv-formats -s schema.json -d "data.*.json"

每次提交都校驗 JSON(pre-commit 掛勾)

要徹底阻止未校驗的 JSON 被提交,請用 husky + lint-staged 設定一個掛勾:

// package.json
{
  "lint-staged": {
    "*.json": [
      "jq empty",                                  // 語法檢查
      "ajv validate -s schemas/$name.schema.json -d"
    ]
  }
}

# 安裝掛勾
npx husky add .husky/pre-commit "npx lint-staged"

對 Python 專案,官方的 pre-commit 框架內建了一個 check-json 掛勾,會對每個暫存檔案執行 json.loads

常見的 JSON 校驗錯誤

校驗失敗時,原因幾乎總在這些之中 —— 每一條都有專門的指南:

常見問題

怎麼檢查一段字串是不是合法 JSON?

try/catch 裡把它傳給 JSON.parse()(JavaScript),或者在 try/except 裡傳給 json.loads()(Python)。沒丟例外就合法。若想免程式地檢查,用 瀏覽器校驗器

可以用正規表示式校驗 JSON 嗎?

不行。JSON 是遞迴文法,正規表示式無法正確表達。請始終使用真正的解析器,例如 JSON.parse()

校驗與解析 JSON 有什麼差別?

解析把文字變成可用的值;校驗只是確認它能夠被解析。實務上一次成功的 parse 就是校驗 —— 它們是同一個操作,只是你只關心合法與否時把結果丟掉。

怎樣對照 schema 校驗 JSON?

JSON Schema,配合 Ajv(JavaScript)或 jsonschema 函式庫(Python)。Schema 校驗檢查型別、必填欄位與約束 —— 而不只是語法。

立刻校驗 JSON —— 不需設定

把 JSON 貼進 JSON 校驗器,即可看到即時的語法錯誤與精確的行列位置。全程在瀏覽器中執行,資料不會離開你的機器。