本文へスキップ
totonoe.tech
システム入力

JSONが読み込めない原因は「最後のカンマ」と「引用符」──エラー別チェックリスト

JSONが読み込めない原因で多いのは、最後の要素のあとのカンマ、シングルクォートや全角の引用符、コメントです。RFC 8259の規則と、Node.jsとPythonで実際に試した結果をもとに、12のエラーを症状・原因・直し方の表で整理します。

この記事のポイント

  • 末尾カンマ・コメント・全角引用符はJSONでは不可。空白は4種類だけ
  • エラー位置は原因の直後を指す。位置番号は0から数える
  • 壊れた箇所はJSONを整えるで行と列を日本語で確かめて直せる
Q.
JSONの最後の要素のあとにカンマがあるとエラーになるのはなぜですか?
A.
JSONの仕様(RFC 8259)では、カンマは要素と要素の区切りにだけ使い、最後の要素のあとには置けないと決まっているためです。JavaScriptのコードや一部の設定ファイルでは許されることがあり、その感覚でJSONを書くと失敗します。最後のカンマを消せば読み込めます。
この記事の作業は、無料のツールでそのままできます(入力は送信されません) JSONを整える 壊れたJSONの場所と原因を日本語で。整形・圧縮・修復もブラウザ内で 開く

JSONを読み込もうとして「Unexpected token」といったエラーが出る。見た目は正しそうなのに、どこが悪いのかわからない。そういうときに疑う場所は、ある程度決まっています。

結論を先に書きます。JSONが読み込めない原因で最も多いのは、最後の要素のあとのカンマ(末尾カンマ)と、半角のダブルクォート以外の引用符です。 コメントを書いたことも、よくある原因です。JSONの仕様であるRFC 8259には、末尾カンマにもコメントにも、書いてよいという規則がありません。この記事では、RFC 8259の規則と、Node.jsとPythonで実際に試した結果をもとに、エラー別のチェックリストを作りました。

JSONの規則は意外と少ない

JSONの文法は、RFC 8259(2017年12月)に定められています。関係する規則を先に整理します。

  • 文字列とキー名は、半角のダブルクォート(“)で囲む
  • 値として書けるのは、オブジェクト、配列、数値、文字列、そして true、false、null の3つのリテラルだけ
  • true、false、null は小文字でなければならない
  • 空白として許されるのは、スペース、タブ、改行(LF)、復帰(CR)の4種類だけ
  • 区切りのカンマは、要素と要素の間にだけ置く
  • コメントを書く規則は存在しない
  • 1つのJSONテキストは1つの値で構成される

エラー別チェックリスト:12の原因

原因ごとに、壊れた例と直し方をまとめました。例は、Node.jsの JSON.parse で実際に確かめたものです。

番号原因壊れた例直し方
1末尾カンマ{“a”:1,} や [1,2,]最後のカンマを消す
2シングルクォート{‘a’:1}ダブルクォートにする
3全角・スマート引用符{“a”:1}半角のダブルクォートにする
4キー名の引用符なし{a:1}“a” と囲む
5コメント{“a”:1 // メモ}コメントを消す
6全角スペース{“a”: 1}(値の前に全角スペース)半角スペースか、削除
7数値の書式01、+1、.5、0x101、1、0.5、16 と書く
8NaN・Infinity{“a”:NaN}null にするか、文字列にする
9リテラルの大文字True、None、undefinedtrue、null
10文字列内の生の改行・タブ“x(改行)y”\n や \t と書く
11バックスラッシュ“C:\Users”“C:\Users” と書く
12BOM・複数のJSON先頭にBOM、{…}{…} と連続BOMを外す、1つずつ読む

末尾カンマとコメントは「使える環境がある」から混乱する

1と5は、JSONを手で書く人が最もよく踏む原因です。

JavaScriptのコードでは、配列やオブジェクトの最後にカンマを書いても構いません。設定ファイルにも、コメントや末尾カンマを許す独自の拡張(JSONCなど)を使うものがあります。そのため、ある環境で動いていたファイルが、別のプログラムではエラーになることがあります。

RFC 8259のJSONでは、どちらも認められません。Node.jsで {“a”:1,} を読み込むと、「位置7でダブルクォートで囲んだキー名が必要」という趣旨のエラーが出ます。位置7はカンマではなく、その次の閉じ括弧 } の場所です。つまり、エラー位置は原因の直後を指すことが多いのです。「次のキー名が来るはずなのに閉じ括弧が来た」と判断した場所が報告されるためです。エラーの位置を見たら、その直前の文字を疑ってみてください。なお、位置番号は1ではなく0から数えます。

引用符は「見た目が似ている別の文字」が混ざる

2と3は、コピーして貼り付けた文章で起きます。ワープロや、チャット画面、文章を整えるツールからJSONをコピーすると、半角のダブルクォート(“)が、カーブした引用符(“ ”)や全角の引用符に置き換わっていることがあります。見た目はほとんど同じで、目では見つかりません。

シングルクォート(‘)も同じです。Pythonの辞書を print した結果をそのまま貼ると、シングルクォートと True、None が混ざって、複数のエラーが同時に出ます。

6の全角スペースも、同じ「見た目が似ている文字」の問題です。JSONで空白として許されるのは先ほどの4種類だけで、全角スペースは含まれません。文字列の中に書いた全角スペースは問題ありませんが、値と値の間に紛れ込むとエラーになります。

数値は書き方に細かい決まりがある

7、8、9は、JavaScriptやPythonの感覚で書くと失敗する部分です。

  • 先頭のゼロ: 01 のように、0のあとに数字を続けた数値は認められません。0 の次に数字が来る書き方は、仕様で禁じられています。郵便番号や電話番号のように先頭の0に意味がある値は、数値ではなく文字列として “0123” と書きます
  • 先頭のプラス記号と、小数点で始まる数: +1 や .5 は認められません。0.5 のように、整数部を省略せずに書きます
  • NaN と Infinity: 仕様に「表現できない数値(InfinityやNaNなど)は許されない」と書かれています。Node.jsでは読み込みに失敗します。ところが、Pythonの標準の json.loads は NaN をそのまま受け付けて、nan として読み込みました。処理系によって結果が違うので、null などに置き換えておくのが安全です
  • true・false・null: 小文字のみです。Pythonの True や None、JavaScriptの undefined は、JSONのリテラルではありません

もう1つ、エラーにはならないのに値が変わる落とし穴があります。桁数の大きな数値です。RFC 8259は、数値の範囲や精度の上限を実装に任せています。多くのソフトが使う倍精度(IEEE 754 binary64)では、整数が正確に扱えるのは -9,007,199,254,740,991 から 9,007,199,254,740,991(2の53乗より1小さい数)までです。RFC 8259も、この範囲の整数は相互運用できる、と書いています。

Node.jsで {“id”:12345678901234567890} を読み込むと、id は 12345678901234567000 になります。20桁のIDを数値のまま扱うと、末尾の桁が失われます。長いIDや口座番号のような値は、文字列で書くのが確実です。

文字列の中身に関する注意

10と11は、文字列の中に特別な文字を直接書いたときの原因です。

仕様では、文字列の中に直接書いてはいけない文字が決まっています。ダブルクォート、バックスラッシュ、そして制御文字(U+0000からU+001Fまで)です。改行やタブは制御文字なので、文字列の中に生のまま入れるとエラーになります。改行は \n、タブは \t と書きます。Pythonでは「Invalid control character」と報告されました。

バックスラッシュは、エスケープの始まりを示す文字です。Windowsのファイルパス “C:\Users” をそのまま書くと、\U という存在しないエスケープになり、エラーです。バックスラッシュ自体を書くときは、2つ重ねて “C:\Users” とします。

BOMと、複数のJSONの連結

12は、データの作り方や保存の仕方に原因がある場合です。

BOM(バイトオーダーマーク) は、ファイルの先頭に付く目に見えない文字(U+FEFF)です。RFC 8259は、ネットワークで送るJSONにBOMを付けてはならないと定めています。一方で、読み込む側がBOMを無視してもよい、とも書いていて、扱いは実装次第です。Node.jsの JSON.parse では、BOMつきの文字列は「予期しないトークン」で失敗しました。保存し直したあとにエラーが出始めたら、BOMを疑います。

複数のJSONの連結 は、ログなどで見かけます。{“a”:1}{“b”:2} のように、値が連続したファイルを JSON.parse に渡すと、「JSONのあとに空白以外の文字がある」というエラーになります。1つのJSONテキストは1つの値で構成されるためです。

直し方の順番

次の順番で見ていくと、原因にたどり着きやすくなります。

  1. エラーに示された位置の、直前の文字を見る(位置は0から数える)
  2. カンマ、引用符、括弧の対応を確かめる
  3. 全角の文字(引用符、スペース、コロン)が混ざっていないか確かめる
  4. 文字列の中の改行、バックスラッシュ、先頭のゼロ、BOMを確かめる

目で探すのが難しいときは、道具に任せるほうが確実です。JSONを整える は、壊れたJSONの場所を、何行目の何が悪いかを日本語で示します。末尾カンマ、全角の引用符、全角スペース、コメント、シングルクォートといった、コピーで壊れるタイプの破損は、ワンクリックで直せます。整形や圧縮をしても、20桁のIDのような長い数値を丸めず、元の文字のまま保ちます。

出典

  • RFC 8259「The JavaScript Object Notation (JSON) Data Interchange Format」(2017年12月)
  • 本文のエラーメッセージと読み込みの結果は Node.js と Python(標準の json モジュール)で確かめたもので、文言は処理系やバージョンで異なります

運営サイト

私たちが運営するサイト