JSON構文エラーの原因とデバッグ実践完全ガイド
JSONパースエラー(SyntaxError)の根本原因、RFC 8259仕様、末尾カンマの問題、BigInt精度落ち防止策、および本番環境での安全なデバッグ技法を徹底解説します。
JSONフォーマッター
データをサーバーに送信せず、すべてブラウザ内で安全に検証・実行できます。
WebアプリケーションでJSONパースエラーが起こる根本的な理由
RFC 8259およびECMA-404規格として標準化されたJSON(JavaScript Object Notation)は、現代のWeb APIや分散システムにおける事実上の標準データ交換フォーマットです。構文の外観はJavaScriptのオブジェクトリテラルと酷似していますが、JSONの文法規則はJavaScriptよりもはるかに厳格に定義されています。
不要なカンマが1つある、シングルクォートで文字列を囲んでいる、あるいは文字列値の中にエスケープされていない制御文字(改行やタブ)が含まれているだけで、JSON.parse()は容赦なくSyntaxError例外をスローして実行を即座に中断します。本番環境で適切にハンドリングされていないJSONパースエラーは、Next.jsなどのフロントエンドでのハイドレーション不一致や、バックエンドAPIでの予期せぬ500 Internal Server Errorを引き起こす原因となります。
頻出する5大JSON構文エラーと正しい修正方法
RFC 8259規格に違反し、パーサーが入力を拒否する代表的な5つの構文エラーパターンです:
- 末尾のカンマ(Trailing Comma): 現代のJavaScriptやTypeScriptでは許容される末尾カンマですが、JSON仕様では配列やオブジェクトの最後の要素の後ろにカンマを置くこと(
{"key": "value",})が固く禁じられています。 - シングルクォート(')の使用: JSONのすべての文字列およびオブジェクトのキーは、必ずダブルクォート(
"key": "value")で囲まなければなりません。シングルクォートやテンプレートリテラル(バックティック)は一切使用できません。 - クォートが省略されたオブジェクトキー: JavaScriptでは
{ id: 100 }と書けますが、JSONでは必ず{"id": 100}のようにキーをダブルクォートで囲む必要があります。 - エスケープされていない制御文字: 文字列値の中に生の改行コードやタブ文字を直接含めることはできません。必ず
\nや\tのようにバックスラッシュでエスケープする必要があります。 - 不正な数値リテラル形式: 先頭に余分なゼロがある数値(
0123)、16進数表記(0x1A)、およびNaNやInfinityはJSON標準の有効な数値ではありません。
// ❌ 不正なJSON (SyntaxErrorが発生する典型例)
{
'name': 'DevUtils',
"version": 2.0,
"features": [
"formatter",
"validator",
]
}
// ✅ 正しいRFC 8259準拠JSON
{
"name": "DevUtils",
"version": 2.0,
"features": [
"formatter",
"validator"
]
}シリアライズ時に発生する循環参照(Circular Reference)エラー
文字列をパースする際のエラーとは異なり、メモリ上のオブジェクトを文字列にシリアライズ(変換)する際に開発者を悩ませる代表的な障害が循環参照です。
オブジェクトが自分自身や祖先ノードを相互に参照している状態でJSON.stringify()を実行すると、JavaScriptランタイムはTypeError: Converting circular structure to JSONという致命的例外を発生させます。JSONはツリー構造(木構造)のみを表現できる仕様であり、循環グラフ構造をサポートしていないためです。
この問題を解決するには、シリアライズ前に循環参照プロパティを手動で削除するか、WeakSetを活用して一度訪問したオブジェクトを追跡・除外するカスタムリプレーサー(Replacer)関数を渡す必要があります。
見落としやすい64ビット整数(BigInt)の精度落ち問題
JavaScriptの標準的な数値型(Number)は、IEEE 754倍精度64ビット浮動小数点数フォーマットを使用しています。この数学的制約により、JavaScriptが丸め誤差なしに正確に表現できる整数の範囲はNumber.MAX_SAFE_INTEGER(2^53 - 1、すなわち9,007,199,254,740,991)までに限られます。
PostgreSQLのBIGINT型カラムや、Twitter(X)のSnowflake ID、Discordの各種オブジェクトIDなどの64ビット整数を純粋な数値としてJSONに含めてAPIで送信すると、クライアント側のJSON.parse()が実行された瞬間に下位ビットが切り捨てられ、データが不可逆的に破損します。例えば9007199254740993というIDは、ブラウザでパースされた時点で自動的に9007199254740992へと化けてしまいます。大規模システムを設計する際は、64ビット整数IDをJSON上で必ず文字列(String)型として扱うのが鉄則です。
// ❌ 危険:64ビット数値をそのまま数値として扱う
const rawData = '{"userId": 9007199254740993}';
const parsed = JSON.parse(rawData);
console.log(parsed.userId); // 出力: 9007199254740992 (下位ビットが消失してデータ破壊!)
// ✅ 安全:API設計段階で文字列として送受信する
const safeData = '{"userId": "9007199254740993"}';
const safeParsed = JSON.parse(safeData);
const realUserId = BigInt(safeParsed.userId); // 正確な値を保持して安全に演算可能本番環境で安全にJSONを運用するためのベストプラクティス
- 必ずtry-catch構文でパース処理を保護する: サードパーティ製APIのレスポンスやWebhookのペイロードが、常に正常なJSONであると盲信してはなりません。
- ZodやAjvによる実行時スキーマ検証の導入:
JSON.parse()の成功後に、オブジェクトが必要なプロパティと正しい型を持っているかを実行時にバリデーションします。 - Content-Typeヘッダーの事前検証: リクエストボディを読み取る前に、相手が
Content-Type: application/jsonを指定しているかを確認します。 - オンラインフォーマッターによる事前構文チェック: 複雑な設定ファイル(tsconfigやpackage.json、モックデータ)をコードベースにコミットする前に、DevUtilsのJSON Formatterで構文の妥当性を検証しましょう。
JSONフォーマッター
無料のオンラインJSON整形ツール。構文エラー検出とインデント設定に対応。ブラウザ内で安全に動作します。