結論

JSONとは、データを「文字」で表すための決まった書き方です。API のやり取りや設定ファイルに使われ、JSONファイルはその文字を保存したものです。

この記事でわかること

  • 6つの型とオブジェクト・配列の書き方の早見表
  • Python・JavaScript・jqで読み書きした実物
  • 書き間違い12例のエラー原文と直し方

2026年10月23日更新|Python 3.11・Node.js 22・jq 1.7で実行確認

JSON は、プログラムの中のデータを文字の並びに書き出し、別のプログラムがそれを読み込んで元のデータに戻すための「共通の書き方」です。言語が違っても同じ形で受け渡せます。

flowchart TD
    A[プログラムのデータ<br>Python の dict・JS のオブジェクト] -->|書き出す<br>dumps・stringify| J[JSON テキスト<br>決まった書き方の文字]
    J -->|保存する| F[JSON ファイル<br>拡張子 .json]
    J -->|送る| W[API のリクエスト<br>とレスポンス]
    F -->|読み込む<br>load・parse| B[別のプログラムのデータ<br>言語が違っても同じ形]
    W -->|読み込む| B

急いでいる人向けに、よく調べられることの答えを先にまとめます。

知りたいこと 答え 詳しい節
JSON とは データを文字で表す書き方 JSONとは
読み方 ジェイソン JSONとは
書き方 {"キー": 値} と [値, 値] 書き方の決まり
使える型 文字列・数値・真偽値・null・オブジェクト・配列 6つの型
JSON ファイルとは JSON を保存した拡張子 .json のテキスト JSONファイルとは
開き方 メモ帳・VS Code・ブラウザ 開き方・編集の仕方
コメントは書ける? 書けない(エラーになる) よくある書き間違い
JavaScript との違い キーは必ず " で囲む・関数は書けない JavaScriptとの違い
1行1件の形式 JSON Lines(.jsonl) JSON Lines

確認環境:Ubuntu 24.04.4 LTS。同じ JSON ファイルを Python 3.11.15 の json モジュール、Node.js v22.22.2 の JSON.parse・JSON.stringify、jq 1.7 で読み書きし、書き間違い12例のエラーを3つの道具で出しました。API のやり取りは Python の http.server で作った手元のサーバーに curl 8.5.0 と Node.js の fetch で送り、ブラウザでの表示は Chromium 141.0.7390.37 で、JSON Schema の検証は Python の jsonschema 4.26.0 で確かめました。仕様は RFC 8259・ECMA-404・json.org、型の対応と既定の動きは Python と MDN のドキュメント、エディタの機能は VS Code の公式ドキュメント(2026年10月21日更新)と Firefox のドキュメント、JSON Schema と JSON Lines はそれぞれの公式サイトで確かめました(確認日 2026年10月23日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JSONとは|JSONファイルの書き方・開き方とエラー例を実物で解説」

JSONとは(意味・読み方・使われる場面)

この節では、JSON という言葉の意味と読み方、どんな場面で使われているのかが分かります。

JSON(JavaScript Object Notation)は、データを人にも機械にも読みやすい文字で表すための書き方(データ形式)です。 json.org の日本語ページでは「軽量のデータ交換フォーマット」と説明され、JavaScript の書き方の一部を元に作られたものの、特定の言語には依存しないとされています。読み方は「ジェイソン」です。

名前に JavaScript と入っていますが、Python・Java・PHP・Go など、ほとんどの言語が JSON を読み書きする仕組みを持っています。「言語が違うプログラムどうしで、データを同じ形で受け渡すための共通語」と考えると分かりやすくなります。

規格 発行 内容
RFC 8259 IETF・2017年12月 インターネットの標準(STD 90)。RFC 7159 を置きかえた
ECMA-404 第2版 Ecma International・2017年12月 JSON の文法(The JSON data interchange syntax)
ISO/IEC 21778 ISO・IEC ECMA-404 のページに番号が載っている国際規格

身近なところでは、次の場面で毎日のように使われています。

1Web API のやり取り

天気・地図・決済などのサービスに問い合わせると、結果が JSON で返ってくる。送るデータも JSON で書くことが多い。

2画面とサーバーの通信

ブラウザの JavaScript が fetch でサーバーからデータを受け取り、画面を書きかえる。

3設定ファイル

package.json(Node.js)、VS Code の settings.json、tsconfig.json など。

4データの保存・書き出し

アプリのデータのバックアップ、ゲームのセーブデータ、サービスからのデータの書き出し。

5ログ

1行に1件の JSON を書く形式(JSON Lines)で、あとから検索・集計しやすくする。

JSONの書き方の決まり(オブジェクト・配列・6つの型)

この節では、JSON の書き方の決まりを、1つのサンプルと早見表で確かめられます。

JSON は「オブジェクト { }」と「配列 [ ]」の2つの入れ物に、6種類の値を入れて組み立てます。 この記事では、次の user.json を例に使います。

{
  "id": 101,
  "name": "佐藤 花子",
  "email": "hanako@example.com",
  "active": true,
  "score": 92.5,
  "tags": ["admin", "editor"],
  "address": {
    "pref": "東京都",
    "zip": "100-0001"
  },
  "manager": null
}
入れ物 書き方 意味 例
オブジェクト { "キー": 値, ... } 名前と値の組の集まり {"pref": "東京都"}
配列 [ 値, 値, ... ] 順番のある値の並び ["admin", "editor"]
型 書き方 例 Python では JavaScript では
文字列(string) " で囲む "佐藤 花子" str string
数値(number) そのまま書く。整数も小数も同じ型 101・92.5 int・float number
真偽値(boolean) 小文字の true・false true bool boolean
null 小文字の null(値が無い) null None null
オブジェクト { } {"zip": "100-0001"} dict object
配列 [ ] ["admin"] list Array

RFC 8259 では、値は「オブジェクト・配列・数値・文字列」か、false・null・true のどれかと決められています。真偽値の2つを1つの型として数えると、6つの型になります。オブジェクトの中にオブジェクトや配列を入れる(入れ子にする)こともできます。上の例の address がそれです。

書くときの細かい決まりです。

決まり 正しい例 誤りの例
キーは必ず "(ダブルクォート)で囲む {"name": "花子"} {name: "花子"}
文字列も " で囲む。' は使えない "花子" '花子'
最後の要素の後ろにカンマを付けない [1, 2] [1, 2,]
コメントは書けない ― // メモ
true・false・null は小文字 true True
数値の先頭に 0 を付けない 12 012
NaN・Infinity は書けない null などで表す NaN
空白・改行は記号の前後に自由に入れてよい 整形しても1行でも同じ意味 ―

文字列の中で特別な文字を書くときは、\ を前に付けます(エスケープ)。RFC 8259 では "・\・制御文字(U+0000〜U+001F)は必ずエスケープすると決められています。

書きたい文字 JSON での書き方
改行 \n
タブ \t
ダブルクォート \"
バックスラッシュ(円記号) \\
任意の文字(UTF-16 の番号) \u3042(あ)

Python で書き出すと、次のとおりエスケープされました。

{"msg": "1行目\n2行目", "quote": "He said \"hi\"", "path": "C:\\Users\\rjc", "tab": "A\tB", "emoji": "😀"}

JSONとJavaScriptのオブジェクトの違い

この節では、見た目がよく似た JavaScript のオブジェクトと JSON が、どこで違うのかが分かります。

JavaScript のオブジェクトはプログラムの中の「データそのもの」、JSON はそれを書き出した「文字」です。 JSON は JavaScript の書き方を元にしていますが、MDN は「JavaScript ならば JSON であるというわけではない」と説明しています。

キーと文字列の囲み

JavaScript{name: 'single'} のように、キーの囲みを省け、' も使える
↔
JSONキーも文字列も必ず " で囲む

JSON.parse に {a: 1} を渡すと SyntaxError になった

書ける値

JavaScript関数・undefined・Date・BigInt・NaN・Infinity も入る
↔
JSON文字列・数値・真偽値・null・オブジェクト・配列だけ

関数と undefined は消え、NaN は null、Date は文字列になった

末尾のカンマ・コメント

JavaScriptどちらも書ける
↔
JSONどちらも書けない

次の節で、3つの道具のエラー原文を確かめる

Node.js で、JSON に無いものを含むオブジェクトを JSON.stringify で JSON にしました。

const obj = {
  name: 'single',          // シングルクォートも書ける(JS の書き方)
  when: new Date("2026-10-23T09:00:00+09:00"),
  hello() { return "hi"; },
  nothing: undefined,
  big: 10n ** 2n === 100n,
  nan: NaN,
  inf: Infinity,
};
console.log(JSON.stringify(obj));
try { JSON.stringify({ n: 10n }); } catch (e) { console.log(e.name + ": " + e.message); }
{"name":"single","when":"2026-10-23T00:00:00.000Z","big":true,"nan":null,"inf":null}
TypeError: Do not know how to serialize a BigInt

関数 hello と undefined の nothing は黙って消え、NaN・Infinity は null に、日付は UTC の文字列になりました。 BigInt はそのままでは JSON にできずエラーです。戻したときに元と同じにならない値があるので、JSON にする前に「送りたいデータが6つの型で表せるか」を確かめます。

JSONファイルとは(拡張子・中身・文字コード)

この節では、JSON ファイルの正体と、保存するときの決まりが分かります。

JSON ファイルは、JSON の文字をそのまま保存したテキストファイルで、拡張子は .json です。 画像やアプリのような特別な形式ではなく、メモ帳でも中身を読めます。RFC 8259 では、ネットワークで使うときの種類(メディアタイプ)を application/json、拡張子を .json と決めています。

user.json を file コマンドと od(中身を16進数で見るコマンド)で調べました。

$ file user.json
user.json: JSON text data
$ wc -c user.json
228 user.json
$ od -A d -t x1z -N 48 user.json
0000000 7b 0a 20 20 22 69 64 22 3a 20 31 30 31 2c 0a 20  >{.  "id": 101,. <
0000016 20 22 6e 61 6d 65 22 3a 20 22 e4 bd 90 e8 97 a4  > "name": "......<
0000032 20 e8 8a b1 e5 ad 90 22 2c 0a 20 20 22 65 6d 61  > ......",.  "ema<

先頭は {(7b)から始まる、ただの文字の並びです。 「佐藤」は e4 bd 90 e8 97 a4 の6バイトで、UTF-8 という文字コードで保存されています。

項目 決まり(RFC 8259) 守らないと
文字コード 閉じた環境の外とやり取りする JSON は UTF-8 日本語が文字化けする
BOM(先頭の目印 EF BB BF) ネットワークで送る JSON の先頭に付けてはいけない Python と Node.js はエラーにした(次の節)
同じキー オブジェクトのキーは重ならないようにする(SHOULD) どれが使われるかは道具しだい
大きな整数 -(2の53乗-1)〜2の53乗-1 の範囲なら、どこでも同じ値で読める 範囲の外は値が変わることがある

最後の2つは、実際に道具によって結果が変わりました。{"id": 9007199254740993, "dup": 1, "dup": 2} を読み込んだ結果です。

Python 3.11 : {'id': 9007199254740993, 'dup': 2, 'price': 0.1}
Node.js 22  : { id: 9007199254740992, dup: 2, price: 0.1 }
jq 1.7      : {"id":9007199254740993,"dup":2,"price":0.1}

Node.js では ...993 が ...992 に変わりました。 JavaScript の数値は2の53乗を超える整数を正しく持てないためです。注文番号やツイートの ID のように大きな整数を送るときは、"9007199254740993" のように文字列にするのが一般的です。同じキー dup は、3つとも後の 2 を使いました。

JSONファイルの開き方・編集の仕方

この節では、パソコン・ブラウザ・コマンドで JSON ファイルを開いて、見やすく整形する方法が分かります。

JSON ファイルはテキストなので、文字を表示できるアプリならどれでも開けます。 目的ごとに使い分けると楽になります。

目的 道具 操作
中身をちょっと見る Windows のメモ帳・Mac のテキストエディット ファイルを右クリック→プログラムから開く
見やすく読む ブラウザ(Chrome・Edge・Firefox) ファイルをブラウザの画面へドラッグ
編集する VS Code などのコードエディタ 色分け・誤りの表示・整形ができる
コマンドで整形・抜き出し jq・python3 -m json.tool jq . user.json
プログラムで扱う Python・JavaScript など 次の節

ダブルクリックで開けないときは、拡張子 .json にアプリが結び付いていないだけです。右クリックの「プログラムから開く」でテキストエディタを選びます。

ブラウザで開く

Chromium 141 で1行に詰めた JSON ファイルを開くと、文字がそのまま表示され、画面の左上に Pretty-print というチェックボックスが出ました。チェックを入れると、改行と空白2つの字下げが付いて読みやすくなりました。ページの種類(document.contentType)は application/json でした。

Firefox には JSON ビューアーが組み込まれています。Firefox のドキュメントでは、application/json で配信されたファイルや URL を色分けして表示し、検索欄での絞り込み、生の JSON の表示と整形、(ネットワークから開いたときは)リクエストとレスポンスのヘッダーの表示ができると説明されています。

VS Code で開いて編集する

VS Code は JSON を色分けし、誤りに波線を引きます。公式ドキュメントでは、ドキュメントの整形(Format Document)のショートカットは次のとおりです。

OS 整形のショートカット
Windows Shift+Alt+F
Mac ⇧⌥F
Linux Ctrl+Shift+I

VS Code の settings.json・tasks.json・launch.json は「JSON with Comments(jsonc)」という別のモードで、// と /* */ のコメントが書けます。 末尾のカンマも受け付けますが、使わないよう警告が出ると公式ドキュメントに書かれています。これは VS Code の設定ファイル用の書き方で、ふつうの JSON ではコメントはエラーになります。

コマンドで整形する(jq・Python)

1行に詰めた JSON と、整形した JSON の大きさを比べました。

$ jq -c . user.json > user.min.json                       # 1行に詰める
$ python3 -m json.tool --no-ensure-ascii user.min.json > user.pretty.json   # 整形する
$ wc -c user.min.json user.pretty.json
179 user.min.json
276 user.pretty.json
179バイト1行に詰めた JSON空白と改行を取った形。API でよく使う
276バイト字下げ4つで整形した JSON中身は同じ。人が読むための形
1.54倍整形による増え方空白と改行のぶんだけ大きくなった

python3 -m json.tool は、何も付けないと日本語を \u4f50\u85e4 のように書きかえました。 日本語のまま整形したいときは --no-ensure-ascii を付けます。Python のドキュメントでは、3.14 からは python -m json でも同じことができ、python -m json.tool も引き続き使えるとされています。

$ python3 -m json.tool user.min.json | head -3
{
    "id": 101,
    "name": "\u4f50\u85e4 \u82b1\u5b50",

整形ツールは、JSON の誤りを見つける道具にもなります。末尾にカンマのあるファイルを渡すと、場所を示して終了コード 1 で止まりました。

$ python3 -m json.tool bad/01_trailing.json
Expecting property name enclosed in double quotes: line 1 column 17 (char 16)

JSONを読み書きする(Python・JavaScript・jq)

この節では、同じ user.json を3つの道具で読み込み、値を取り出し、書きかえて保存した実物を確かめられます。

どの言語でも「JSON テキスト → 言語のデータ(読み込み)」と「言語のデータ → JSON テキスト(書き出し)」の2つの操作があります。

操作 Python JavaScript jq
文字列から読む json.loads(s) JSON.parse(s) echo '…' | jq .
ファイルから読む json.load(f) JSON.parse(await readFile(p, "utf8")) jq . file.json
文字列へ書き出す json.dumps(obj) JSON.stringify(obj) jq -c .
整形して書き出す json.dumps(obj, indent=2) JSON.stringify(obj, null, 2) jq .
値を取り出す user["address"]["pref"] user.address.pref jq '.address.pref'

Python(json モジュール)

import json

with open("user.json", encoding="utf-8") as f:
    user = json.load(f)                    # JSON → Python の dict

print(type(user).__name__, user["name"], user["address"]["pref"])
for k, v in user.items():
    print(f"{k:8} {type(v).__name__}")

user["tags"].append("viewer")              # 書きかえて
user["active"] = False
with open("user_out.json", "w", encoding="utf-8") as f:
    json.dump(user, f, ensure_ascii=False, indent=2)   # Python → JSON ファイル

print(json.dumps({"name": "花子"}))                     # 既定は \u エスケープ
print(json.dumps({"name": "花子"}, ensure_ascii=False)) # 日本語のまま
dict 佐藤 花子 東京都
id       int
name     str
email    str
active   bool
score    float
tags     list
address  dict
manager  NoneType
{"name": "\u82b1\u5b50"}
{"name": "花子"}

JSON の true は Python の True、null は None になりました。 保存した user_out.json では、"active": false に変わり、tags に "viewer" が加わっていました。Python のドキュメントでは、ensure_ascii は既定で True で、ASCII 以外の文字をすべてエスケープすると説明されています。日本語のまま保存したいときは ensure_ascii=False を付けます。書き方のレシピは、関連記事「Python JSON 読み書き|コピペレシピと実行結果・3.14対応」で扱っています。

JavaScript(JSON.parse・JSON.stringify)

import { readFile, writeFile } from "node:fs/promises";

const text = await readFile("user.json", "utf8");
const user = JSON.parse(text);                 // JSON テキスト → オブジェクト
console.log(typeof user, user.name, user.tags.length, user.manager);

user.score += 1;
await writeFile("user_out2.json", JSON.stringify(user, null, 2) + "\n");
console.log(JSON.stringify({ id: 1, name: "花子" }));   // 1行(最小)
object 佐藤 花子 2 null
{"id":1,"name":"花子"}

JSON.stringify は、日本語をエスケープせずにそのまま書き出しました。2つ目の引数で書き出す項目を選び、3つ目の引数で字下げの数を決めます。JSON.parse のエラーの原因と整形の方法は、関連記事「JSON.parseとJSON.stringifyの使い方|エラー原因と整形」で扱っています。

jq(コマンドで読む・書きかえる)

jq は、JSON を取り出したり形を変えたりするコマンドです。公式サイトでは「軽量で柔軟なコマンドラインの JSON プロセッサ」と説明され、2026年10月23日時点の最新は 1.8.2(2026年6月20日)です。手元では Ubuntu 24.04 の apt の 1.7 を使いました。

$ jq '.name' user.json
"佐藤 花子"
$ jq -r '.name' user.json                  # -r で " を外す
佐藤 花子
$ jq '.tags[0]' user.json                  # 配列の0番目
"admin"
$ jq '.address.pref' user.json             # 入れ子をたどる
"東京都"
$ jq -c '{id, name, pref: .address.pref}' user.json    # 形を変える
{"id":101,"name":"佐藤 花子","pref":"東京都"}
$ jq '.tags | length' user.json
2
$ jq '.missing' user.json                  # 無いキーは null
null
$ jq '.active = false | .tags += ["viewer"]' user.json > user_jq.json   # 書きかえて保存
$ jq -c . user_jq.json
{"id":101,"name":"佐藤 花子","email":"hanako@example.com","active":false,"score":92.5,"tags":["admin","editor","viewer"],"address":{"pref":"東京都","zip":"100-0001"},"manager":null}

. で全体、.キー でオブジェクトの値、[番号] で配列の要素を指します。 番号は0から数えます。条件で絞る・集計するなどの書き方は、関連記事「jqの使い方|逆引き40例と実務レシピを全部実行結果つきで解説」で扱っています。

よくある書き間違いとエラー原文(末尾のカンマ・シングルクォート・コメント)

この節では、JSON を手で書いたときにつまずきやすい12の書き間違いと、Python・Node.js・jq が出したエラー原文、直し方が分かります。

12個のファイルを作り、同じものを3つの道具で読み込みました。

== Python 3.11(json.load)
01_trailing.json: JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 17 (char 16)
02_single.json: JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
03_comment.json: JSONDecodeError: Expecting ',' delimiter: line 2 column 10 (char 11)
04_nokey.json: JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
05_nocomma.json: JSONDecodeError: Expecting ',' delimiter: line 2 column 2 (char 9)
06_zero.json: JSONDecodeError: Expecting ',' delimiter: line 1 column 8 (char 7)
07_true.json: JSONDecodeError: Expecting value: line 1 column 8 (char 7)
08_empty.json: JSONDecodeError: Expecting value: line 1 column 1 (char 0)
09_bom.json: JSONDecodeError: Unexpected UTF-8 BOM (decode using utf-8-sig): line 1 column 1 (char 0)
10_fullwidth.json: JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
11_nan.json: OK {'n': nan}
12_ctrl.json: JSONDecodeError: Invalid control character at: line 1 column 10 (char 9)
== Node.js 22(JSON.parse)
01_trailing.json: SyntaxError: Expected double-quoted property name in JSON at position 16 (line 1 column 17)
02_single.json: SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
03_comment.json: SyntaxError: Expected ',' or '}' after property value in JSON at position 11 (line 2 column 10)
04_nokey.json: SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
05_nocomma.json: SyntaxError: Expected ',' or '}' after property value in JSON at position 9 (line 2 column 2)
06_zero.json: SyntaxError: Unexpected number in JSON at position 7 (line 1 column 8)
07_true.json: SyntaxError: Unexpected token 'T', "{"ok": True}" is not valid JSON
08_empty.json: SyntaxError: Unexpected end of JSON input
09_bom.json: SyntaxError: Unexpected token '', "{"a": 1}" is not valid JSON
10_fullwidth.json: SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
11_nan.json: SyntaxError: Unexpected token 'N', "{"n": NaN}" is not valid JSON
12_ctrl.json: SyntaxError: Bad control character in string literal in JSON at position 9 (line 1 column 10)
== jq 1.7
01_trailing.json: jq: parse error: Expected another key-value pair at line 1, column 17
02_single.json: jq: parse error: Invalid numeric literal at line 1, column 5
03_comment.json: jq: parse error: Invalid numeric literal at line 2, column 12
04_nokey.json: jq: parse error: Invalid numeric literal at line 1, column 3
05_nocomma.json: jq: parse error: Expected separator between values at line 2, column 4
06_zero.json: {"n":12}
07_true.json: jq: parse error: Invalid numeric literal at line 1, column 12
08_empty.json: (何も出力しない)
09_bom.json: {"a":1}
10_fullwidth.json: jq: parse error: Invalid numeric literal at line 1, column 9
11_nan.json: {"n":null}
12_ctrl.json: jq: parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 2, column 7
書き間違い ファイルの中身 直し方
01 末尾のカンマ {"a": 1, "b": 2,} 最後の要素の後ろのカンマを消す
02 シングルクォート {'a': 1} ' を " に置きかえる
03 コメント "a": 1 // コメント コメントを消す。説明は別のキーかドキュメントに書く
04 キーを囲んでいない {a: 1} {"a": 1} にする
05 カンマの付け忘れ "a": 1 改行 "b": 2 要素の間に , を入れる
06 先頭が0の数値 {"n": 012} 12。0 で始まる番号は文字列 "012" にする
07 大文字の True {"ok": True} 小文字の true
08 空のファイル (0バイト) 中身が届いているか、読む前に確かめる
09 先頭に BOM EF BB BF {"a": 1} BOM なしの UTF-8 で保存し直す
10 全角の引用符 {“a”: 1} 半角の " にする(文書からのコピーで起きやすい)
11 NaN {"n": NaN} null にするか、文字列にする
12 文字列の中の改行 "改行 改行 入り" \n と書く

エラー文の「line 行 column 列」や「position 位置」は、読み込みが止まった場所です。 原因はその場所か、その少し前にあります。たとえば末尾のカンマ(01)は、カンマの次の } の位置(17列目)で止まっています。

3つの道具の結果を見比べると、道具によって受け付ける範囲が少し違うことが分かります。

ファイル Python 3.11 Node.js 22 jq 1.7 規格(RFC 8259)では
06 先頭が0 エラー エラー 12 として読んだ 誤り
09 BOM エラー エラー 読んだ 送る側が付けてはいけない
11 NaN nan として読んだ エラー null にした 誤り
08 空 エラー エラー 何も出さず終了 誤り

ある道具で読めても、ほかの道具では読めないことがあります。 自分で書く JSON は、規格どおりに書いておくのが安全です。Python のドキュメントにも、RFC は NaN と無限大を認めていないが、json モジュールは既定でそれらを受け付けて書き出すと書かれています。書き出すときに止めたい場合は json.dumps(obj, allow_nan=False) で、手元では ValueError: Out of range float values are not JSON compliant が出ました。

BOM 付きのファイルを Python で読むときは、エラー文のとおり encoding="utf-8-sig" を指定すると {'a': 1} として読めました。Python の JSONDecodeError のうち Expecting value が出る原因の切り分けは、関連記事「JSONDecodeError: Expecting valueの直し方」で扱っています。

  • 1キーと文字列はすべて半角の " で囲んだ' や全角の引用符が混じっていない
  • 2最後の要素の後ろにカンマが無い行を消したあと、1つ前の行に残りやすい
  • 3コメントを書いていない// や /* */ はふつうの JSON ではエラー
  • 4true・false・null が小文字Python の True・None をそのまま書いていない
  • 5BOM なしの UTF-8 で保存したエディタの保存形式で選べる
  • 6保存したら整形ツールに通したjq . や python3 -m json.tool がエラーを出さない

APIでのJSONのやり取り(curlで送受信)

この節では、API が JSON をどう送り、どう返すのかを、手元のサーバーと curl で実際に確かめられます。

API で JSON を送るときは、本文(ボディ)に JSON の文字を入れ、ヘッダーの Content-Type: application/json で「中身は JSON です」と伝えます。 受け取る側はこのヘッダーを見て、本文を JSON として読み込みます。

flowchart TD
    C[クライアント<br>curl・ブラウザ・アプリ] -->|POST 本文に JSON<br>Content-Type application/json| S[サーバー<br>JSON を読み込む]
    S -->|正しい JSON| OK[201 Created<br>登録したデータの JSON]
    S -->|書き間違い 400<br>種類が違う 415| NG[エラー内容の JSON]

Python の標準ライブラリだけで、ユーザーを取得・登録する小さな API を作りました。

import json
from http.server import BaseHTTPRequestHandler, HTTPServer

USERS = {101: {"id": 101, "name": "佐藤 花子", "active": True}}

class Handler(BaseHTTPRequestHandler):
    def send_json(self, status, body):
        data = json.dumps(body, ensure_ascii=False).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)

    def do_GET(self):
        uid = int(self.path.rsplit("/", 1)[-1])
        if uid in USERS:
            self.send_json(200, USERS[uid])
        else:
            self.send_json(404, {"error": "not found"})

    def do_POST(self):
        if self.headers.get("Content-Type", "").split(";")[0] != "application/json":
            return self.send_json(415, {"error": "Content-Type must be application/json"})
        raw = self.rfile.read(int(self.headers.get("Content-Length", 0)))
        try:
            body = json.loads(raw)
        except json.JSONDecodeError as e:
            return self.send_json(400, {"error": "invalid JSON", "detail": str(e)})
        new_id = max(USERS) + 1
        USERS[new_id] = {"id": new_id, **body}
        self.send_json(201, USERS[new_id])

HTTPServer(("127.0.0.1", 38201), Handler).serve_forever()

受け取る(GET)

$ curl -i http://127.0.0.1:38201/api/users/101
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.11.15
Date: Fri, 23 Oct 2026 08:41:58 GMT
Content-Type: application/json
Content-Length: 52

{"id": 101, "name": "佐藤 花子", "active": true}

送る(POST)

$ curl -i -X POST http://127.0.0.1:38201/api/users \
    -H 'Content-Type: application/json' \
    -d '{"name": "鈴木 一郎", "active": false}'
HTTP/1.0 201 Created
Content-Type: application/json
Content-Length: 53

{"id": 102, "name": "鈴木 一郎", "active": false}

手元の curl 8.5.0 には --json があり、ヘッダーを自分で書かずに送れます。-v で送ったヘッダーを見ると、Content-Type と Accept の2つが自動で付いていました。Content-Length: 25 は、「高橋 次郎」(UTF-8 で13バイト)を含む本文のバイト数です。

$ curl -v --json '{"name": "高橋 次郎"}' http://127.0.0.1:38201/api/users
> POST /api/users HTTP/1.1
> Host: 127.0.0.1:38201
> User-Agent: curl/8.5.0
> Content-Type: application/json
> Accept: application/json
> Content-Length: 25
>
< HTTP/1.0 201 Created
{"id": 104, "name": "高橋 次郎"}

間違えたとき(400・415)

$ curl -X POST http://127.0.0.1:38201/api/users -H 'Content-Type: application/json' -d "{'name': 'x'}"
{"error": "invalid JSON", "detail": "Expecting property name enclosed in double quotes: line 1 column 2 (char 1)"}
$ curl -X POST http://127.0.0.1:38201/api/users -d '{"name": "x"}'
{"error": "Content-Type must be application/json"}

2つ目は JSON の中身は正しいのに、415 になりました。 curl の -d は、ヘッダーを付けないと Content-Type: application/x-www-form-urlencoded(フォームの形式)で送るためです。API に JSON を送って 400 や 415 が返ったら、本文の書き方とヘッダーの両方を確かめます。curl のオプションの使い方は、関連記事「curlコマンドの使い方|よく使うオプションとAPIの確認方法」で扱っています。

JavaScript の fetch で送受信する

const res = await fetch("http://127.0.0.1:38201/api/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "田中 美咲", active: true }),  // オブジェクト → JSON
});
console.log(res.status, res.headers.get("content-type"));
const data = await res.json();                                // JSON → オブジェクト
console.log(data, typeof data.id);
201 application/json
{ id: 105, name: '田中 美咲', active: true } number

送るときは JSON.stringify で文字にし、受け取ったら res.json() でオブジェクトに戻します。 サーバーが JSON ではなく HTML のエラーページを返すと、res.json() は次のエラーになりました(Node.js 22 の Response に HTML の文字を渡して確かめたもの)。

SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

JSON Schemaで中身を検証する

この節では、JSON の「形」は正しくても「中身」が期待と違うときに、JSON Schema で見つける方法が分かります。

JSON Schema は、「このキーは必須」「この値は整数」「0〜100の範囲」といった JSON の決まりを、JSON で書いておくための仕様です。 公式サイトでは、2026年10月23日時点の最新版は 2020-12 です。

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "ユーザー",
  "type": "object",
  "required": ["id", "name", "email"],
  "properties": {
    "id":     { "type": "integer", "minimum": 1 },
    "name":   { "type": "string", "minLength": 1 },
    "email":  { "type": "string", "pattern": "^[^@]+@[^@]+$" },
    "active": { "type": "boolean" },
    "score":  { "type": "number", "minimum": 0, "maximum": 100 },
    "tags":   { "type": "array", "items": { "type": "string" } }
  },
  "additionalProperties": true
}

Python の jsonschema 4.26.0 で、正しいデータ(user.json)と、書き方は正しいが中身が違うデータを検証しました。

import json, sys
from jsonschema import Draft202012Validator

schema = json.load(open("user.schema.json", encoding="utf-8"))
v = Draft202012Validator(schema)
for path in sys.argv[1:]:
    data = json.load(open(path, encoding="utf-8"))
    errors = sorted(v.iter_errors(data), key=lambda e: list(e.path))
    print(f"{path}: {'OK' if not errors else f'{len(errors)} 件のエラー'}")
    for e in errors:
        print(f"  {'/'.join(map(str, e.path)) or '(全体)'}: {e.message}")
$ echo '{"id": "101", "name": "", "score": 120, "tags": ["admin", 1]}' > user_bad.json
$ python validate.py user.json user_bad.json
user.json: OK
user_bad.json: 5 件のエラー
  (全体): 'email' is a required property
  id: '101' is not of type 'integer'
  name: '' should be non-empty
  score: 120 is greater than the maximum of 100
  tags/1: 1 is not of type 'string'

user_bad.json は JSON としては正しく読み込めますが、決まりに合わない点が5つ見つかりました。 API の入り口でこの検証をしておくと、おかしなデータを保存する前に止められます。

よく使うキーワード 意味
type 型(object・array・string・number・integer・boolean・null)
required 必ずあるべきキーの一覧
properties キーごとの決まり
minimum・maximum 数値の下限・上限
minLength・pattern 文字列の長さ・正規表現
items 配列の要素の決まり
enum 決まった値のどれか
additionalProperties 書いていないキーを許すか

VS Code では、JSON ファイルに $schema キーを書くか、設定の json.schemas でファイル名とスキーマを結び付けると、入力中に誤りを表示し、候補を出します。公式ドキュメントでは、$schema キーを書く方法は VS Code 独自のもので、JSON の中身が変わるため受け取る側が想定していないことがある、と注意されています。

JSON Lines(.jsonl)とは

この節では、ログや大量のデータでよく使う JSON Lines の形と、ふつうの JSON との違いが分かります。

JSON Lines は、1行に1つの JSON を書き、改行で区切る形式です。 公式サイトでは、UTF-8 で BOM を付けない、各行が正しい JSON の値、行の終わりは \n、拡張子は .jsonl が使える、とされています。メディアタイプは application/jsonl が提案されていますが、まだ正式には決まっていません。

ふつうの JSON(配列)

ファイル全体で1つの値。[{...}, {...}]

全部を読み終えないと使えない

追記するには最後の ] の前に入れ直す

JSON Lines(.jsonl)

1行に1件。行ごとに独立した JSON

1行ずつ読んで処理できる

ファイルの末尾に1行足すだけで追記できる

アクセスログを JSON Lines で書き、Python と jq で読みました。

{"time": "2026-10-23T09:00:01+09:00", "path": "/", "status": 200, "ms": 12}
{"time": "2026-10-23T09:00:02+09:00", "path": "/api/users", "status": 201, "ms": 48}
{"time": "2026-10-23T09:00:03+09:00", "path": "/api/users/999", "status": 404, "ms": 5}
{"time": "2026-10-23T09:00:04+09:00", "path": "/login", "status": 500, "ms": 230}
import json
with open("access.jsonl", encoding="utf-8") as f:
    rows = [json.loads(line) for line in f if line.strip()]   # 1行ずつ読む
print(len(rows), "行", [r["status"] for r in rows])
print("4xx/5xx:", [r["path"] for r in rows if r["status"] >= 400])
try:
    json.load(open("access.jsonl", encoding="utf-8"))           # 全体を1つの JSON として読むと…
except json.JSONDecodeError as e:
    print("JSONDecodeError:", e)
4 行 [200, 201, 404, 500]
4xx/5xx: ['/api/users/999', '/login']
JSONDecodeError: Extra data: line 2 column 1 (char 76)
$ jq -c 'select(.status >= 400) | {path, status}' access.jsonl
{"path":"/api/users/999","status":404}
{"path":"/login","status":500}
$ jq -s 'map(.ms) | add / length' access.jsonl     # -s で配列にまとめて平均
73.75

JSON Lines のファイルを json.load で丸ごと読むと、2行目で Extra data のエラーになりました。 1行ずつ json.loads で読むのが正しい読み方です。jq は1行ずつ処理し、-s を付けると全体を1つの配列にまとめます。

JSONとCSV・XML・YAMLの違い

この節では、よく比べられるデータ形式と JSON の違いが、早見表で分かります。

JSON は入れ子のデータを短く書け、ほとんどの言語が標準で読めるので、API のやり取りでよく選ばれます。 表の形だけなら CSV、人が手で書く設定なら YAML、文書の構造や属性を細かく表すなら XML が選ばれることがあります。

形式 見た目 入れ子 コメント よく使う場面
JSON {"name": "花子"} できる 書けない API・設定・データの受け渡し
CSV name,pref の行 できない(表だけ) 決まりが無い 表のデータの受け渡し
XML <name>花子</name> できる <!-- --> 文書・業務システムのデータ・RSS
YAML name: 花子 字下げでできる # 設定ファイル(CI・Kubernetes など)

同じデータを5つの形式で書いて読み込んだ比較と、選び方の判断表は、関連記事「CSV・JSON・XML・YAML・TOMLの違いと使い分け|同じデータで比較」で扱っています。

よくある質問

Q. JSON とは簡単に言うと何ですか? A. データを文字で表すための決まった書き方です。{"name": "花子", "age": 20} のように、名前と値の組を { } で、並びを [ ] で書きます。言語が違うプログラムの間でデータを受け渡すときによく使われます。

Q. JSON の読み方は? A. 「ジェイソン」と読みます。JavaScript Object Notation の頭文字です。

Q. JSON ファイルとは何ですか?どうやって開きますか? A. JSON の文字を保存した、拡張子 .json のテキストファイルです。メモ帳・テキストエディット・VS Code で開け、ブラウザに読み込むと整形して表示できます(Chromium 141 では Pretty-print のチェックボックスが出ました)。

Q. JSON にコメントは書けますか? A. 書けません。// を入れると、Python・Node.js・jq のどれもエラーになりました。VS Code の settings.json などは JSON with Comments という別のモードなので、コメントが書けます。

Q. JSON の末尾にカンマを付けるとどうなりますか? A. エラーになります。Python では Expecting property name enclosed in double quotes、Node.js では Expected double-quoted property name in JSON と出ました。最後の要素の後ろのカンマを消します。

Q. JSON でシングルクォートは使えますか? A. 使えません。キーも文字列も "(ダブルクォート)で囲みます。{'a': 1} は3つの道具すべてでエラーになりました。

Q. JSON で使えるデータ型は? A. 文字列・数値・真偽値(true・false)・null・オブジェクト・配列の6つです。日付は文字列で、関数は書けません。

Q. JSON と JavaScript のオブジェクトの違いは? A. JSON はデータを書き出した文字で、キーと文字列を必ず " で囲み、関数・undefined・コメント・末尾のカンマは書けません。JSON.stringify で JavaScript のオブジェクトを JSON にすると、関数と undefined は消えました。

Q. JSON の配列とは? A. [ と ] で囲んだ、順番のある値の並びです。["admin", "editor"] のように書き、0番目から数えます。jq では .tags[0] で最初の要素を取り出せます。

Q. 日本語が \u82b1 のようになるのはなぜですか? A. Python の json.dumps と python3 -m json.tool は、既定で ASCII 以外の文字をエスケープするためです。ensure_ascii=False か --no-ensure-ascii を付けると日本語のまま出ました。

Q. JSON Lines(jsonl)とは? A. 1行に1つの JSON を書く形式です。ログのように1件ずつ追記するデータに向き、1行ずつ読んで処理できます。

Q. JSON Schema とは? A. JSON の中身の決まり(必須のキー・型・範囲)を JSON で書くための仕様で、2026年10月23日時点の最新版は 2020-12 です。決まりに合わないデータを、保存する前に見つけられます。

Q. JSON と XML の違いは? A. どちらも入れ子のデータを表せます。JSON は {"name": "花子"} のように短く書け、XML は <name>花子</name> のようにタグで囲み、属性やコメントも書けます。

まとめ

  • JSON は、データを文字で表す決まった書き方(読み方はジェイソン)。RFC 8259 と ECMA-404 で決められ、言語をまたいでデータを受け渡すのに使う。
  • 入れ物はオブジェクト { } と配列 [ ]、値は文字列・数値・真偽値・null・オブジェクト・配列の6つ。キーと文字列は必ず " で囲む。
  • JSON ファイルは拡張子 .json の UTF-8 のテキスト。メモ帳・VS Code・ブラウザで開け、jq や python3 -m json.tool で整形と誤りの確認ができる。
  • 末尾のカンマ・シングルクォート・コメントなど12の書き間違いは、Python・Node.js・jq で異なるエラー文になり、道具によっては読めてしまうものもあった。規格どおりに書くのが安全。
  • API では本文に JSON、ヘッダーに Content-Type: application/json。ヘッダーが無いと 415、書き間違いは 400 になった。
  • 中身の決まりは JSON Schema(2020-12)で検証し、ログのように1件ずつ増えるデータは JSON Lines で書く。

参考・出典

確認日はいずれも 2026年10月23日です。

  • IETF「RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format」:https://www.rfc-editor.org/rfc/rfc8259
  • Ecma International「ECMA-404 The JSON data interchange syntax」:https://ecma-international.org/publications-and-standards/standards/ecma-404/
  • json.org「JSON の紹介」:https://www.json.org/json-ja.html
  • MDN Web Docs「JSON」:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON
  • Python ドキュメント「json --- JSON エンコーダおよびデコーダ」:https://docs.python.org/3/library/json.html
  • jq 公式サイト:https://jqlang.org/
  • Visual Studio Code「JSON editing in Visual Studio Code」:https://code.visualstudio.com/docs/languages/json
  • Firefox Source Docs「JSON viewer」:https://firefox-source-docs.mozilla.org/devtools-user/json_viewer/index.html
  • JSON Schema「Specification」:https://json-schema.org/specification
  • JSON Lines:https://jsonlines.org/
  • @IT「JSON(ジェイソン)」:https://atmarkit.itmedia.co.jp/ait/articles/1602/29/news046.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JSONとは|JSONファイルの書き方・開き方とエラー例を実物で解説」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?