SyntaxError: Unexpected token < in JSON at position 0 を修正する方法

SyntaxError: Unexpected token < in JSON at position 0 のエラーは、待ち受けていた JSON ではなく、JSON 以外のデータ (通常は HTML) を JavaScript コードで受け取ったことを示しています。この問題を修正するには、受け取ったデータを検証して、問題について判断します。fetch() または JSON.parse() を使用している場合は、コンソールにデータを記録して、不正な URL、サーバーエラー、変数の割り当て、文字エンコーディングの問題などの一般的な問題を確認します。


このガイドは、SyntaxError: Unexpected token < in JSON at position 0 の修正に利用できます。また、以下に示す同様な他の一般的なエラーにも適用できます。

概要

これらのエラーは、JavaScript コードが JSON の受け取りを待ち受けていたにも関わらず、代わりに何か別のもの (おそらく、サーバーサイドエラーの形式の HTML) を受け取ったことを示しています。この問題を解決するには、待ち受けていた JSON の代わりに取得したものについて調べて、何が問題なのかを判断する必要があります。

詳細

通常、このエラーは、サーバーが JSON ではなく HTML (通常は <DOCTYPE html> または <html> で始まる) を返す際に発生します。有効な JSON が < という記号から始まることはないため、JSON パーサーでは当該のデータが有効な JSON ではないことをただちに認識し、前述のエラーメッセージのいずれかを生成します。

このエラーを修正するには、待ち受けていた JSON ではなく、HTML (または他の何か) が返された理由を明らかにする必要があります。このためには、解析対象のデータをコンソールに記録する必要があります。

fetch() を使用している場合

以下のようなコードの場合、この方法を使用します。

fetch('https://example.com/some/path/to/json')
.then(function (response) {
    return response.json();
})
.then(function (data) {
    // Do something with data
});

このケースでは、response.json() の実行を試みて、サーバーから返されたデータを JSON として解析できなかったときにエラーがスローされます。このエラーを処理してサーバーから返されたレスポンス本文の生テキストを表示する関数を追加することで、コンソールに記録できます (以下のコメント行に関する説明を参照)。

var responseClone; // 1
fetch('https://example.com/some/path/to/json')
.then(function (response) {
    responseClone = response.clone(); // 2
    return response.json();
})
.then(function (data) {
    // Do something with data
}, function (rejectionReason) { // 3
    console.log('Error parsing JSON from response:', rejectionReason, responseClone); // 4
    responseClone.text() // 5
    .then(function (bodyText) {
        console.log('Received the following instead of valid JSON:', bodyText); // 6
    });
});

番号が付けられたコメントのある各行について説明します。

  1. response の本文は一度しか読み込むことができないので、response オブジェクトのクローンを保持するために responseClone 変数が必要になります。response.json() が呼び出されると、オリジナルの response の本文が読み込まれます。これにより、JSON 解析エラーを処理する際にこの本文を再度読み込むことができなくなります。responseresponseClone にクローンすることで、同じレスポンス本文を 2 つ用意できます。1 つはオリジナルの responseresponse.json() とともに使用します。もう 1 つは response.json() が失敗した場合に、responseClone.text() とともに使用します。
  2. この行では、サーバーから受け取ったレスポンスのクローンを responseClone 変数に格納します。
  3. 2 番目の関数の引数は、response.json() の呼び出しに続く then() 関数に渡されます。この 2 番目の関数は、response.json() からのプロミスが拒否された場合 (つまり、JSON エラーが発生した場合) に呼び出されます。
  4. この行では、拒否された response.json() プロミスからの rejectionReasonresponseClone をログに記録し、必要に応じて検証できるようにします (たとえば、HTTP ステータスコードは多くの場合、デバッグに役立ちます)。
  5. サーバーからのレスポンス本文は、JSON としての解析は行わずに、生テキストとして処理します。
  6. 調査を行うために本文テキストをコンソールに記録します。

JSON.parse() を使用している場合

エラーをスローするコードが以下のような場合は、この方法を使用します。

JSON.parse(data);

このケースでは、エラーが発生したときにデータをコンソールに記録して、その内容を確認することができます。

try {
    JSON.parse(data);
}
catch (error) {
    console.log('Error parsing JSON:', error, data);
}

その後の処理

JSON 解析エラーの原因となっているデータを確認できれば、待ち受けていた有効な JSON を取得できない原因を知る手がかりになるでしょう。こうしたエラーを発生させる最も一般的な問題は次のとおりです。