Railsのエラー『SyntaxError: Unexpected token in JSON at position X』の解決方法

Railsのエラー『SyntaxError: Unexpected token in JSON at position X』の解決方法

Railsアプリケーションで「SyntaxError: Unexpected token in JSON at position X」というエラーが発生することがあります。このエラーは、JSONデータをパースする際に無効な構文が含まれている場合に発生します。エラーの位置(`position X`)は、問題が発生したJSONの文字列内の具体的な箇所を示します。この記事では、このエラーの発生条件と解決方法について詳しく説明します。

1. エラーの概要と発生条件

「SyntaxError: Unexpected token in JSON at position X」は、Railsアプリケーション内でJSONを扱う際に、パース処理が失敗した場合に発生します。一般的な発生条件は以下のとおりです。

  • 無効なJSONフォーマット(例えば、カンマの位置ミス、クオートの抜けなど)
  • エンコードやエスケープ処理のミス
  • サーバーからのレスポンスがJSONではない
  • 不要な文字列が含まれている

2. エラーの具体例

例えば、以下のようなJSONデータをRailsのフロントエンドでパースしようとした場合にエラーが発生します。

const jsonString = '{ "name": "Alice", "age": 25, }'; // 末尾のカンマが余分
const data = JSON.parse(jsonString); // ここでエラー

3. JSONの構文エラーの確認方法

JSONの構文エラーが原因である場合、オンラインのJSONバリデーター(JSONLint など)を使用して検証できます。以下のようなエラーメッセージが出る場合は、JSONの記述ミスを修正する必要があります。

4. 余分なカンマの削除

JavaScriptのオブジェクトリテラルでは末尾のカンマは許容される場合がありますが、JSONでは無効です。以下のように修正します。

const jsonString = '{ "name": "Alice", "age": 25 }'; // 修正後
const data = JSON.parse(jsonString);

5. ダブルクオートの使用

JSONでは、キーと値の文字列はダブルクオート(`”`)で囲む必要があります。シングルクオート(`’`)を使用するとエラーになります。

const jsonString = "{ 'name': 'Alice', 'age': 25 }"; // NG
const jsonString = '{ "name": "Alice", "age": 25 }'; // OK

6. Rails側のレスポンスがJSON形式か確認

RailsのコントローラーがJSONを正しく返しているかを確認します。`render json:` を使用してJSONを返している場合、適切にエンコードされているかチェックします。

render json: { name: "Alice", age: 25 }

もしレスポンスが文字列として返されている場合、以下のように`JSON.parse`の前に`console.log(response)`で内容を確認します。

fetch('/api/users')
  .then(response => response.text()) // JSONではなくテキストとして取得
  .then(text => console.log(text)) // レスポンスを確認
  .then(text => JSON.parse(text)) // JSONに変換

7. JSONレスポンスに余計なデータが含まれていないか確認

RailsのコントローラーがJSON以外のデータ(例えばデバッグ用のHTMLタグなど)を返していないか確認します。

def index
  puts "デバッグログ" # これがレスポンスに含まれる可能性がある
  render json: { name: "Alice", age: 25 }
end

デバッグログなどがレスポンスに含まれると、クライアント側でJSONパースエラーになります。デバッグ出力を削除するか、`Rails.logger.debug` を使用して標準出力のみに記録するようにします。

8. RailsのAPIモードで適切なヘッダーを設定

Rails APIモードを使用している場合、JSONレスポンスを適切に扱うために以下のように`before_action`でヘッダーを設定します。

class ApplicationController < ActionController::API
  before_action :set_default_response_format

  private

  def set_default_response_format
    request.format = :json
  end
end

9. `JSON.parse`の代わりに`try`を使用

JavaScriptの`JSON.parse`は無効なJSONが渡されるとエラーを投げます。エラーを防ぐために`try-catch`を使用すると、安全に処理できます。

try {
  const jsonString = '{ "name": "Alice", "age": 25, }';
  const data = JSON.parse(jsonString);
  console.log(data);
} catch (error) {
  console.error("JSONパースエラー:", error.message);
}

10. JSONエンコーディングの確認

Railsでは、JSONエンコーディングの際に`to_json`メソッドを使用しますが、正しいエンコードになっているかを確認します。

user = { name: "Alice", age: 25 }
puts user.to_json # 正しくJSON化されているかチェック

11. `ActiveSupport::JSON` を利用する

Railsには`ActiveSupport::JSON`という便利なモジュールがあります。これを使用すると、より堅牢なJSONパースが可能になります。

require 'active_support/json'

json_string = '{"name": "Alice", "age": 25}'
data = ActiveSupport::JSON.decode(json_string)
puts data["name"] # => "Alice"

12. `config.force_ssl = true` の確認

本番環境でこのエラーが発生する場合、`config/environments/production.rb` で `force_ssl` の設定を見直してください。HTTPSを強制している場合、意図しないリダイレクトが発生し、JSONデータが壊れることがあります。

config.force_ssl = false