MeWrite Docs

SyntaxError: Unexpected token in JSON

JSONのパース時に構文エラーが発生した際のエラー

概要

JSON.parse()でJSON文字列を解析する際、JSONの構文が正しくない場合に発生するエラーです。APIレスポンスやファイル読み込み時によく発生します。

エラーメッセージ

SyntaxError: Unexpected token '<' in JSON at position 0
SyntaxError: Unexpected token 'u' in JSON at position 0
SyntaxError: Unexpected end of JSON input

原因

  1. HTMLレスポンス: APIがエラーページ(HTML)を返している
  2. undefined/nullのパース: JSON以外の値をパースしようとした
  3. 末尾カンマ: 配列やオブジェクトの末尾に余分なカンマ
  4. シングルクォート: JSONではダブルクォートのみ有効
  5. コメント: JSONはコメントをサポートしていない
  6. BOM: UTF-8 BOMが含まれている

解決策

1. レスポンスの内容を確認

1
2
3
4
5
6
7
8
9
// Bad: 直接パース
const data = JSON.parse(response);

// Good: まず内容を確認
console.log(response);
console.log(typeof response);

// 文字列の先頭を確認
console.log(response.substring(0, 100));

2. fetchでのエラーハンドリング

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
async function fetchData() {
  const response = await fetch('/api/data');

  // レスポンスのContent-Typeを確認
  const contentType = response.headers.get('content-type');

  if (!contentType || !contentType.includes('application/json')) {
    const text = await response.text();
    console.error('Non-JSON response:', text);
    throw new Error('Expected JSON response');
  }

  if (!response.ok) {
    throw new Error(`HTTP error: ${response.status}`);
  }

  return response.json();
}

3. try-catchで安全にパース

1
2
3
4
5
6
7
8
9
function safeJsonParse(str) {
  try {
    return JSON.parse(str);
  } catch (e) {
    console.error('JSON parse error:', e.message);
    console.error('Input:', str?.substring(0, 200));
    return null;
  }
}

4. JSON構文を修正

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// Bad: 末尾カンマ
const badJson = '{"name": "John", "age": 30,}';

// Good
const goodJson = '{"name": "John", "age": 30}';

// Bad: シングルクォート
const badJson2 = "{'name': 'John'}";

// Good: ダブルクォート
const goodJson2 = '{"name": "John"}';

// Bad: コメント
const badJson3 = `{
  "name": "John" // this is a comment
}`;

// Good: コメントなし
const goodJson3 = '{"name": "John"}';

5. APIレスポンスがHTMLの場合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// サーバーが認証エラーでログインページを返している可能性
async function fetchWithAuth() {
  const response = await fetch('/api/data', {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Accept': 'application/json'
    }
  });

  // 401/403チェック
  if (response.status === 401 || response.status === 403) {
    // 再認証が必要
    window.location.href = '/login';
    return;
  }

  return response.json();
}

6. 空レスポンスの処理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
async function fetchData() {
  const response = await fetch('/api/data');
  const text = await response.text();

  // 空の場合
  if (!text) {
    return null;
  }

  return JSON.parse(text);
}

7. Node.jsでファイル読み込み

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const fs = require('fs');

// Bad: BOMが含まれている可能性
const data = JSON.parse(fs.readFileSync('data.json', 'utf8'));

// Good: BOMを除去
function readJsonFile(path) {
  let content = fs.readFileSync(path, 'utf8');
  // BOMを除去
  if (content.charCodeAt(0) === 0xFEFF) {
    content = content.slice(1);
  }
  return JSON.parse(content);
}

8. デバッグ用バリデーション

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function validateJson(str) {
  try {
    JSON.parse(str);
    return { valid: true };
  } catch (e) {
    // エラー位置を特定
    const match = e.message.match(/position (\d+)/);
    const position = match ? parseInt(match[1]) : 0;

    return {
      valid: false,
      error: e.message,
      position,
      context: str.substring(Math.max(0, position - 20), position + 20)
    };
  }
}

よくある間違い

  • APIエラー時のレスポンスをそのままパースしようとする
  • localStorageから取得した値がundefinedの場合
  • ダブルエンコードされたJSON("{\\"name\\":\\"John\\"}"

関連エラー

参考リンク

JavaScript の他のエラー

最終更新: 2025-12-13