← 全部文章

JSON 第 0 位 Unexpected Token u:在解析 undefined

「Unexpected token u」錯誤表示你呼叫了 JSON.parse(undefined)。看清楚為何 undefined 變成 "undefined"、如何防範,以及一個安全解析輔助函式。

SyntaxError: Unexpected token 'u', "undefined" is not valid JSON(舊版引擎:Unexpected token u in JSON at position 0)幾乎總是代表你呼叫了 JSON.parse(undefined)。JavaScript 把 undefined 字串化成文字 "undefined",於是 parser 在開頭那個 u 上卡住。下面說明原因與如何修。

錯誤長什麼樣

// V8 (Chrome / Node / Edge)
SyntaxError: "undefined" is not valid JSON
SyntaxError: Unexpected token 'u', "undefined" is not valid JSON
SyntaxError: Unexpected token u in JSON at position 0   // 較舊的 V8

// Firefox
SyntaxError: JSON.parse: unexpected character at line 1 column 1

// Safari
SyntaxError: JSON Parse error: Unexpected identifier "undefined"

位置 0 的 u 就是字串 "undefined" 的第一個字母 —— parser 根本沒拿到真正的資料。

為什麼會這樣:你解析了 undefined

JSON.parse() 會先把它的引數強制轉成字串。傳進 undefined 它就會去解析字面文字 "undefined",而那不是合法 JSON。值是 undefined 通常因為:

  • 一個變數或函式引數從來沒有被賦值
  • 一個物件屬性不存在(拼錯或物件結構不對):obj.missing
  • 一個 async 值還沒就緒(在 await 之前就解析了)
  • 把一個沒有 return 的函式當成資料來源

壞掉的例子

const cached = localStorage.getItem('settings'); // key 不存在 → null,OK
const draft  = window.appState?.draft;            // 屬性不存在 → undefined
const data   = JSON.parse(draft);                 // ❌ "undefined" is not valid JSON

修好的例子

// 解析前先 guard
const data = draft ? JSON.parse(draft) : null;

// 或者一個安全的 helper
function safeParse(text, fallback = null) {
  if (typeof text !== 'string' || text.trim() === '') return fallback;
  try { return JSON.parse(text); } catch { return fallback; }
}
const data2 = safeParse(draft);

注意:JSON.parse(null) 不會 拋錯 —— 它回傳 null —— 而 localStorage.getItem() 對不存在的 key 回傳的是 null(不是 undefined)。所以一個 u 錯誤明確指向一個 undefined 值,而不是 storage 缺 key。

SyntaxError vs TypeError:為什麼你拿到的是 這個

一個細微但有用的細節:JSON.parse(undefined) 拋的是 SyntaxError,不是 TypeError。為什麼?因為規範規定 JSON.parse 會先把引數 強制轉成字串"undefined")再解析該字串。錯誤是「這段字串不是合法 JSON」,而不是「你傳了錯誤的型別」。這也是為什麼 JSON.parse(undefined)JSON.parse("undefined") 會產生完全相同的「position 0」錯誤。

對比一下確實會做型別檢查的 API,例如 JSON.stringify(BigInt(1))TypeError,或 JSON.parse(Symbol())TypeError(Symbol 無法強制轉字串)。如果你要 catch parse 錯誤,用 err instanceof SyntaxError 來縮窄範圍,把 資料錯誤引數錯誤 分開處理。

怎麼修 —— 一步步來

  1. 印出輸入:console.log(typeof src, src) 緊貼在 parse 之前。如果印出 undefined,那就是元兇。
  2. 追蹤它應該被設定的位置 —— 一個未初始化的 state 欄位、缺失的引數、或者一個物件上根本不存在的屬性。
  3. 加上 guardif (src))或一個 safeParse fallback,別讓缺失值跑到 JSON.parse()
  4. 如果是 async,請確定解析前先 await 這個值。

常見問題

「Unexpected token u in JSON at position 0」是什麼意思?

你把 undefined 傳給了 JSON.parse()。它變成字串 "undefined",開頭的 u 不是合法的 JSON 起始字元。

它跟「token o」或「token <」錯誤是同一個嗎?

同一家族,不同值。u = undefinedtoken o = 一個物件被字串化成 [object Object]token < = 一個 HTML 回應。錯誤裡的那個字元告訴你實際傳進去的是什麼。

為什麼 JSON.parse(null) 不會丟同樣的錯?

"null" 是合法 JSON,所以 JSON.parse(null) 會回傳 null。只有 undefined(→ "undefined")會觸發這個 u 錯誤。

立刻修復