常見 JSON 語法錯誤與修正方法
整理實務上最常遇到的八種 JSON 語法錯誤——結尾逗號、單引號、BOM、NDJSON——並提供具體修正方式。
SyntaxError: Unexpected token } in JSON at position 47 大概是現代開發
裡最沒幫助的錯誤訊息。解析器告訴你它在哪裡放棄,而不是哪裡出了錯。
本文整理八種佔據幾乎所有「JSON 壞了」工單的語法錯誤,並逐一說明如何
修正。
為何「Unexpected token」訊息沒幫助
大多數 JSON 解析器是狀態機,遇到第一個非預期的位元組就中止。它回報的 位置 是解析器發現不對勁的地方,通常已經是真正錯誤的下游。第 3 行 的缺逗號,會以「unexpected token」出現在第 4 或第 5 行。
兩個習慣有幫助:
- 永遠驗證整份文件。不要修一行就重跑;先修完再驗證,因為下個錯誤 常常要等前一個錯誤修掉才會浮現。
- 當錯誤位置已超過檔案結尾(4710 個字元的檔案卻說
position 4711), 代表文件被截斷——把注意力放在未閉合的括號與引號上。
JSON 驗證工具 會針對每種錯誤類別給出 可讀的原因說明。
1. 結尾逗號
最常見的錯誤。JavaScript 允許結尾逗號,JSON 不允許。
{
"a": 1,
"b": 2,
}
修正——把閉合括號前那個逗號移除:
{
"a": 1,
"b": 2
}
陣列也適用:[1, 2, 3,] 同樣不合法。
2. 缺少或多餘的逗號
物件或陣列中,每個值與下一個值之間必須恰好一個逗號:
{
"a": 1
"b": 2
}
修正——在 1 之後補上逗號。鏡像版本是 {"a": 1,, "b": 2},多了一個。
3. 單引號與未加引號的鍵
JavaScript 物件字面值很寬容;JSON 不寬容。所有字串(包括物件鍵) 都必須使用雙引號。
不合法:
{ name: 'Ada', role: "admin" }
合法:
{ "name": "Ada", "role": "admin" }
如果你是從 console 或 stack trace 貼 JS 物件,這幾乎一定是第一個壞掉 的地方。JSON 修復工具 會自動為你加引號、把單 引號改成雙引號。
4. JSON 內的註解
JSON 沒有註解。//、/* */、# 全部是語法錯誤。
{
// user record
"id": 42
}
修正——把註解移除,或移到 JSON 外部(旁邊的檔案、外層 schema,或者
真的非要的話,用 _comment 鍵內嵌)。VS Code 用於 tsconfig.json 的
JSONC 允許註解,但它不是 JSON,大多解析器會拒絕。
5. 字串中未跳脫的字元
JSON 字串內以下字元 必須 跳脫:
"→\"\→\\- 控制字元(U+0000 至 U+001F)——例如字面上的換行必須寫成
\n, tab 寫成\t。
常見錯誤——直接貼上字面換行進字串:
{ "message": "line one
line two" }
修正:
{ "message": "line one\nline two" }
斜線 / 可以選擇性跳脫為 \/,但不是必要。
6. BOM 與編碼問題
UTF-8 的 BOM 是三個位元組 EF BB BF,某些編輯器會寫在檔頭。JSON 規格
禁止檔頭出現 BOM。嚴格解析器(Node 的 JSON.parse、Go 的
encoding/json、部分設定下的 Python json)會以「unexpected token
at position 0」拒絕。
症狀——檔案在編輯器看起來沒問題,但用 hex viewer 會發現開頭 { 之前
有非列印字元。
修正——重新存成「UTF-8 無 BOM」。多數編輯器在編碼選單中有這個選項。 命令列:
sed -i '1s/^\xEF\xBB\xBF//' broken.json
7. JSONP 與 Python 字面值輸出
兩種常被誤認為 JSON 的非 JSON 格式:
- JSONP——
callback({"a":1});。這是把 JSON 形狀當引數的 JS 函式呼叫。把外層的 callback 與結尾分號去掉就會得到 JSON。 - Python
repr輸出——{'a': 1, 'b': True, 'c': None}。單引號、大寫True/False/None。在 Python 中要產生真正的 JSON,用json.dumps而非print。
JSON 修復工具 兩者都能處理。
8. 截斷或串接的 JSON / NDJSON
兩種失敗模式:
- 截斷——檔案在文件中途被切斷。解析器會在輸入結尾失敗,因為括號未閉合。把實際檔案大小與預期對比,必要時重新下載。
- 串接——兩份合法 JSON 文件首尾相連:
{"a":1}{"b":2}。若中間有換行,這是NDJSON(或 JSON Lines),是日誌串流的常見格式。請逐行解析,而非當成單一文件:
for (const line of text.split("\n")) {
if (!line.trim()) continue;
const record = JSON.parse(line);
// ...
}
快速找出並修正
排錯流程:
- 把文件丟進 JSON 驗證工具——它會回報第一個錯誤與最可能的原因。
- 若是結構性錯誤(結尾逗號、單引號、未加引號的鍵、BOM),用 JSON 修復工具 一次正規化。
- 兩個都試過還是錯,那這份文件大概是被截斷,或根本不是 JSON(HTML 錯誤頁、Python repr、JSONP)。檢視開頭與結尾各 100 個位元組通常就會發現。
延伸閱讀
- 在 JavaScript 中安全解析 JSON——在程式碼裡優雅處理這些錯誤。
- 什麼是 JSON?——本文那些錯誤違反的語法規則。