← 全部文章

JSON 資料之後出現非空白字元:修復方法

此錯誤代表一個完整 JSON 值之後還有多餘內容 —— 連在一起的物件、被當作單塊解析的 NDJSON,或結尾的雜訊。如何找出並移除多餘資料。

SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data 表示解析器成功讀到了一個完整的 JSON 值 —— 然後在它後面又發現了更多非空白內容。JSON 頂層只允許一個值,因此後面接著的任何東西都是錯誤。下面說「多餘資料」是怎麼來的以及怎麼修。

錯誤長什麼樣

// Firefox
SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data
  at line 1 column 18 of the JSON data

// V8 (Chrome / Node / Edge)
SyntaxError: Unexpected non-whitespace character after JSON at position 17
SyntaxError: Unexpected token { in JSON at position 17   // 較舊的措辭

// Python(類比)
json.decoder.JSONDecodeError: Extra data: line 1 column 18 (char 17)

報的位置指向有效值之後的第一個字元 —— 「多餘資料」就從那裡開始。

為什麼會這樣

原因 1 —— 兩個 JSON 值接在一起

// ❌ 兩個物件首尾相接 —— 一個有效值,然後還有更多
{"id":1}{"id":2}
//      ^ 第 8 位置:JSON 資料後出現了非空白

// ✅ 用陣列包起來
[{"id":1},{"id":2}]

原因 2 —— NDJSON / JSON Lines 被當成一團解析

日誌檔案和串流 API 經常會發出一行一個 JSON 物件(NDJSON)。JSON.parse() 只讀第一行的值,遇到下一行就掛了。

// ❌ 對整個檔案做 JSON.parse
{"event":"login"}
{"event":"logout"}

// ✅ 一行一行解析
const rows = text
  .split('\n')
  .filter(Boolean)
  .map((line) => JSON.parse(line));

原因 3 —— 尾巴上的垃圾或重複的回應

// ❌ 多餘文字、被複製了一遍的 payload,或尾端分號
{"ok":true};
{"ok":true}  // 代理伺服器追加的偵錯行
extra

JSON-RPC 與其他帶分幀的串流

如果你正在消費一個協定 —— stdio 上的 JSON-RPC、Language Server Protocol (LSP)、Debug Adapter Protocol —— 多個 JSON 訊息按設計就是從同一條頻道流過去的。它們各自帶了一層分幀層,告訴你下一條訊息有多長,正是為了讓你不用在同一個緩衝區裡解析兩個值:

Content-Length: 87\r\n
\r\n
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}Content-Length: 42\r\n
\r\n
{"jsonrpc":"2.0","id":1,"result":{...}}

規則是:讀 Content-Length 標頭,然後讀剛好那麼多位元組,再解析一個 JSON 值,然後迴圈。如果你把整條頻道一口吃下再一次解析,就會撞上「unexpected non-whitespace character after JSON data」,因為裡面有很多個值。

對 NDJSON 來說,對應的規則是「按 \n 切,逐行解析」。共通主題是:一串 JSON 訊息總得有一層分幀;裸接不是合法的 JSON。

怎麼修 —— 一步一步

  1. 跳到報錯位置 —— 從那裡開始的所有內容就是「多餘資料」。看看緊接在第一個完整值後面的是什麼。
  2. 有多個值? 如果你本來想做清單,用 [ … ] 陣列把它們包起來,用逗號分隔。
  3. NDJSON / JSON Lines? 按換行切,逐行解析 —— 不要一次解析整個檔案。
  4. 尾巴上有垃圾? 解析前去掉多餘字元(分號、重複的 payload、偵錯輸出)。
  5. 正在做串流? 確認你沒有把多個回應拼到同一個緩衝區再解析。

常見問題

「unexpected non-whitespace character after JSON data」是什麼意思?

解析器讀到一個有效的 JSON 值,然後在後面發現了更多內容。JSON 只允許一個頂層值,因此後續字元是非法的。

怎麼解析多個 JSON 物件?

如果是接在一起的,用陣列包起來。如果是一行一個(NDJSON / JSON Lines),按換行切,再單獨 JSON.parse() 每一行。

這跟「Unexpected end of JSON input」是同一回事嗎?

它們相反。本錯誤表示資料太多(完整值後面還有東西);「Unexpected end of JSON input」 表示資料太少(值被截斷)。

立刻修復