土薯工具 Toolshu.com 登錄 用戶注冊

JSON 解析報錯看不懂,是因爲你在看錯誤的地方

作者:bhnw 於 2026-04-27 15:20 發佈 3次瀏覽 收藏 (0)

看到 JSON 解析報錯,大部分人第一反應是去檢查 JSON 格式有沒有寫錯。但很多時候,問題根本不在 JSON 本身——而是你傳進去的根本就不是 JSON。

這篇文章按報錯信息分類,每種告訴你它實際在說什麼、根因在哪、怎麼修。


Unexpected token '<', "<!DOCTYPE "... is not valid JSON

這是最常見的一種,幾乎每個前端開發者都遇到過。

它的意思不是"你的 JSON 格式不對",而是"你根本沒收到 JSON,你收到的是一個 HTML 頁面"。

爲什麼會收到 HTML?常見原因:

  • 接口 URL 寫錯了,打到了一個不存在的路由,服務器返回了 404 頁面
  • 沒有登錄權限,服務器把你重定向到了登錄頁
  • 服務器報錯了,返回了 500 錯誤頁面
  • 本地開發時接口代理沒配好,請求打到了前端開發服務器,返回了 index.html
// 出問題的代碼
fetch('/api/user')
  .then(res => res.json())  // 如果 res 是 HTML,這裏直接報錯
  .then(data => console.log(data));

// 正確做法:先檢查響應狀態
fetch('/api/user')
  .then(res => {
    if (!res.ok) {
      throw new Error(`HTTP error: ${res.status}`);
    }
    // 還是不放心,可以先看看 content-type
    const contentType = res.headers.get('content-type');
    if (!contentType || !contentType.includes('application/json')) {
      throw new Error(`Expected JSON, got: ${contentType}`);
    }
    return res.json();
  })
  .then(data => console.log(data))
  .catch(err => console.error(err));

遇到這個報錯,先不要看 JSON,先看網絡請求。打開瀏覽器 DevTools → Network → 找到那個請求 → 看 Response 標籤裏實際返回了什麼。大概率是一個 HTML 頁面,裏面有錯誤信息,那纔是真正的線索。


Unexpected token 'u', "undefined" is not valid JSON

你調用了 JSON.parse(undefined)

undefined 不是字符串,不是 JSON,傳進去當然報錯。通常發生在這幾種情況:

// 情況1:變量沒有初始化
let data;
JSON.parse(data);  // data 是 undefined

// 情況2:從對象裏取了一個不存在的字段
const response = { result: '{"name":"Alice"}' };
JSON.parse(response.data);  // response.data 是 undefined,不是 result

// 情況3:localStorage 裏沒有存過這個 key
const saved = localStorage.getItem('user');  // 返回 null
JSON.parse(saved);  // JSON.parse(null) 其實不報錯,但如果 key 不存在...
// 某些情況下會拿到 undefined

修復方式就是在解析前做判斷:

const raw = localStorage.getItem('user');
if (raw) {
  const user = JSON.parse(raw);
}

// 或者更防禦性的寫法
function safeParse(str) {
  if (!str || typeof str !== 'string') return null;
  try {
    return JSON.parse(str);
  } catch {
    return null;
  }
}

SyntaxError: Unexpected end of JSON input

JSON 是完整的,但傳進去之前被截斷了。

JSON.parse('{"name":"Alice"');  // 缺少閉合的 }
JSON.parse('');                  // 空字符串
JSON.parse('[1, 2, 3');          // 數組沒有閉合

實際項目裏,最常見的原因是網絡請求中斷——響應體只傳了一半,連接就斷了。另一種是後端在拼 JSON 字符串的時候(本來就不應該手拼)邏輯有 bug,字符串沒有完整結束。

排查方式:打印一下收到的原始字符串,看看它在哪裏結束的:

fetch('/api/data')
  .then(res => res.text())  // 先用 text() 而不是 json()
  .then(text => {
    console.log('原始響應:', text);
    console.log('最後20個字符:', text.slice(-20));
    return JSON.parse(text);
  });

TypeError: Converting circular structure to JSON

這個發生在 JSON.stringify() 的時候,不是 JSON.parse()

循環引用是指對象直接或間接地引用了自己:

const obj = { name: 'Alice' };
obj.self = obj;  // obj 引用了自己

JSON.stringify(obj);  // TypeError: Converting circular structure to JSON

實際項目裏最容易踩到這個坑的地方是把 Express 的 reqres 對象直接 stringify:

// 錯誤:req 內部有循環引用
app.post('/log', (req, res) => {
  console.log(JSON.stringify(req));  // 報錯
});

// 正確:只取你需要的字段
console.log(JSON.stringify({
  method: req.method,
  url: req.url,
  body: req.body,
  headers: req.headers
}));

如果確實需要序列化一個可能有循環引用的對象,可以用自定義 replacer:

function safeStringify(obj) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) return '[Circular]';
      seen.add(value);
    }
    return value;
  });
}

JSON 裏有 undefined、函數、Date 對象,序列化後消失或變形

JSON 不支持 JavaScript 的所有數據類型,有些值在 JSON.stringify() 時會被悄悄處理掉,不報錯但結果不對:

const obj = {
  name: 'Alice',
  fn: function() {},       // 函數
  undef: undefined,        // undefined
  date: new Date(),        // Date 對象
  nan: NaN,                // NaN
  inf: Infinity            // Infinity
};

console.log(JSON.stringify(obj));
// {"name":"Alice","date":"2026-04-11T02:13:20.000Z","nan":null,"inf":null}
// fn 和 undef 直接消失了!date 變成了 ISO 字符串,NaN 和 Infinity 變成了 null

如果你的對象裏有這些類型,序列化前要先處理:

// Date 對象:手動轉成 ISO 字符串
const data = {
  created_at: new Date().toISOString()  // 明確控制格式
};

// undefined 值:改成 null
const data = {
  middleName: null  // 不要 undefined
};

排查思路總結

遇到 JSON 報錯,按這個順序來:

第一步:看原始內容,不要先看報錯信息。 response.json() 改成 response.text() 先打印出來,確認收到的到底是什麼。

第二步:看報錯位置。 報錯信息裏會有 position 或行號,定位到那個字符附近看看是什麼。

第三步:對着報錯類型查原因。 < 開頭是 HTML;undefined 是變量沒初始化;end of input 是被截斷了;circular structure 是循環引用。

格式問題(單引號、末尾逗號、鍵名沒引號這類)粘到 JSON 格式化工具 裏,智能修復會幫你定位並自動修正,不用自己數字符。

发现周边 发现周边
評論區

加載中...