← 全部文章

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",解析器就在开头那个 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" 的第一个字母 —— 解析器根本没拿到真实数据。

为什么会这样:你解析了 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 错误。

立刻修复