可驗證、安全、可維護的 JSON — Practice
最後一單元:把語法、型別、延伸格式串成「能上線」的 JSON 應用, 並養成安全、可維護的習慣。
綜合運用:六種型別、巢狀、以及(用 JSONC 時)註解。
{
// 服務設定
"name": "my-app",
"port": 8080,
"debug": false,
"database": {
"host": "db.example.com",
"pool": { "min": 1, "max": 10 }
},
"features": ["auth", "search"],
"admins": [1, 2, 3],
"limits": { "timeout": 30, "retries": 3 },
"banner": null
}
name / port / debug:字串、數字、布林。
database:巢狀物件(含 pool)。
features / admins:字串與數字的陣列。
limits:鍵值映射。
banner:null——「沒設定」也要明確表達。
// 註解:只能在 JSONC 環境使用。
# 驗證格式(Node 一行) node -e "JSON.parse(require('fs').readFileSync(0,'utf8'))" < config.json # 或 Python python3 -c "import json,sys; json.load(sys.stdin)" < config.json # 美化 / 壓縮 jq . config.json # 美化 jq -c . config.json # 壓成一行 cat config.json | jq . # 管道用法 # 用 Schema 驗證(用 ajv / jsonschema) npx ajv-cli validate -s schema.json -d data.json
讀取 JSON 有兩個經典陷阱:
「不安全 merge」把 __proto__ 等特殊鍵寫進物件原型,可能癱瘓或控制應用程式:
{ "__proto__": { "isAdmin": true } } { "constructor": { "prototype": { } } }
JSON.parse 本身是安全的);
危險的是任意 merge(如 `lodash.merge`、手寫遞迴合併)。合併前先檢查鍵名、或改用
structuredClone / Object.assign 之外的白名單合併。
用正規表示式解析 JSON 幾乎必然出錯(字串內有逗號、括號、跳脫…)。永遠用標準解析器。
| 錯誤 | 後果 | 修正 |
|---|---|---|
| 尾逗號 | 解析失敗 | 移除最後一項逗號 |
| 單引號 / 無引號鍵 | 解析失敗 | 全改雙引號 |
| 寫了註解 | 解析失敗 | 改用 JSONC 環境或移除 |
| 字串內裸換行 | 解析失敗 | 用 \n |
| 大整數超過 2^53 | 精度失真 | 改用字串 |
| 把日期當數字/物件 | 型別不符 | 用 ISO 字串慣例 |
| 多筆資料堆在一起 | 解析失敗 | 包成陣列,或改用 JSON Lines |
prettier 統一格式。null,不要省略欄位造成歧義。jq 在終端機把它整形、過濾一遍——你會發現 JSON 已經「看懂了」。