JSON完全ガイド:基本構文・バリデーション・スキーマ・実践ツール
JSONとは
JSON(JavaScript Object Notation)は、データを構造化して記述するための軽量なテキストフォーマットです。もともとJavaScriptのオブジェクト表記法から派生しましたが、現在では言語に依存しない汎用的なデータ交換形式として広く使われています。
REST APIのレスポンス、設定ファイル、データベースへの保存など、Web開発のあらゆる場面でJSONは登場します。そのシンプルさと可読性の高さが、XMLに代わってデファクトスタンダードとなった理由です。
JSONの仕様は RFC 8259 およびECMA-404で定義されています。規格に準拠したパーサーは同一の入力に対して同一の結果を返すため、言語をまたいだ相互運用性が高いことが大きな特徴です。
基本構文とデータ型
JSONで使用できるデータ型は、以下の6種類に限定されています。
| データ型 | 説明 | 例 |
|---|---|---|
| 文字列 | ダブルクォートで囲む | "Hello" |
| 数値 | 整数または浮動小数点 | 42, 3.14 |
| 真偽値 | true または false | true |
| null | 空の値 | null |
| オブジェクト | キーと値のペア | {"key": "value"} |
| 配列 | 値の順序付きリスト | [1, 2, 3] |
オブジェクトの構文
オブジェクトは波括弧 {} で囲み、キーと値のペアをコロンで区切ります。複数のペアはカンマで区切ります。
{
"name": "田中太郎",
"age": 30,
"isActive": true,
"email": "tanaka@example.com"
}
重要なルールとして、キーは必ずダブルクォートで囲む必要があります。シングルクォートやクォートなしはJSONとして無効です。
配列の構文
配列は角括弧 [] で囲み、値をカンマで区切ります。異なるデータ型を混在させることも可能です。
{
"fruits": ["りんご", "みかん", "ぶどう"],
"mixed": [1, "hello", true, null]
}
ネスト構造
オブジェクトと配列は自由にネスト(入れ子)にできます。これにより、複雑なデータ構造を表現できます。
{
"company": "Example Corp",
"employees": [
{
"name": "佐藤",
"department": "開発部",
"skills": ["JavaScript", "Python"]
},
{
"name": "鈴木",
"department": "デザイン部",
"skills": ["Figma", "CSS"]
}
]
}
よくあるエラーと対策
JSONの構文エラーは、開発中に頻繁に遭遇する問題です。主な原因と対策を見ていきましょう。
1. 末尾カンマ(トレイリングカンマ)
JavaScriptでは許容される末尾カンマですが、JSONでは構文エラーになります。
// 無効なJSON
{
"name": "田中",
"age": 30,
}
// 有効なJSON
{
"name": "田中",
"age": 30
}
2. シングルクォートの使用
JSONではダブルクォートのみが有効です。
// 無効なJSON
{'name': '田中'}
// 有効なJSON
{"name": "田中"}
3. コメントの記述
JSON仕様にはコメント構文がありません。// や /* */ を含むとパースエラーになります。設定ファイルでコメントが必要な場合は、JSON5やJSONCの使用を検討してください(後述)。
4. 数値の先頭ゼロ
0 以外の数値で先頭にゼロを付けると無効になります。
// 無効なJSON
{"code": 0123}
// 有効なJSON
{"code": 123}
5. 文字列内の特殊文字のエスケープ漏れ
文字列内の特定の文字はバックスラッシュでエスケープする必要があります。
| 文字 | エスケープシーケンス |
|---|---|
| ダブルクォート | \" |
| バックスラッシュ | \\ |
| 改行 | \n |
| タブ | \t |
| キャリッジリターン | \r |
{
"message": "彼は\"こんにちは\"と言いました",
"path": "C:\\Users\\田中",
"multiline": "1行目\n2行目"
}
JSONフォーマッターを使えば、JSONのバリデーションとエラー箇所の特定を瞬時に行えます。
整形のベストプラクティス
可読性と保守性を高めるために、以下のベストプラクティスを心がけましょう。
インデントの統一
JSONファイルを人が読む場合は、2スペースまたは4スペースのインデントを使います。チームで統一することが重要です。
{
"settings": {
"theme": "dark",
"fontSize": 14,
"autoSave": true
}
}
キーの命名規則
APIの設計では、キーの命名規則を統一しましょう。一般的にはキャメルケース(camelCase)またはスネークケース(snake_case)が使われます。
{
"userName": "tanaka",
"createdAt": "2026-03-08T10:00:00Z"
}
適切なデータ型の選択
文字列として数値を格納するのは避け、適切なデータ型を使いましょう。
// 避けるべきパターン
{"price": "1000", "isAvailable": "true"}
// 推奨パターン
{"price": 1000, "isAvailable": true}
ミニファイ(最小化)とプリティプリント
APIやストレージではミニファイしてペイロードサイズを削減し、設定ファイルや人が読む用途ではプリティプリントを使います。JSONフォーマッターで一瞬で変換できます。
JSON Schema:JSONの構造を検証する
JSON Schemaは、JSONデータの構造と制約を記述するための語彙です。「有効なJSONドキュメントとはどういう形か」を定義し、受け取ったデータを自動的に検証できます。
JSON Schemaを使う理由
- APIリクエスト・レスポンスのボディを検証する
- 設定ファイルの期待する形を文書化する
- フォームやドキュメントを自動生成する
- アプリケーションのロジックに到達する前にデータ品質の問題を検出する
JSON Schemaの基本例
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": {
"type": "integer",
"description": "ユーザーの一意な識別子"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"roles": {
"type": "array",
"items": {
"type": "string",
"enum": ["admin", "editor", "viewer"]
}
}
}
}
よく使うJSON Schemaキーワード
| キーワード | 対象 | 説明 |
|---|---|---|
type |
すべて | データ型を指定 |
required |
オブジェクト | 必須プロパティ名のリスト |
properties |
オブジェクト | 各プロパティの形を定義 |
minimum / maximum |
数値 | 数値範囲の制約 |
minLength / maxLength |
文字列 | 文字列長の制約 |
pattern |
文字列 | 正規表現による制約 |
enum |
すべて | 固定値セットへの制限 |
items |
配列 | 配列要素のスキーマ |
format |
文字列 | セマンティックフォーマット("email", "date-time" 等) |
JSON Schemaはほぼすべての言語のライブラリでサポートされています。代表的なバリデーターとして、JavaScriptの ajv、Pythonの jsonschema、Goの gojsonschema などがあります。
JSON vs JSON5 vs JSONC:どれを使うべきか
標準のJSONは相互運用性を優先して意図的に厳格に設計されています。JSON5とJSONCはJSONの上位互換で、主に設定ファイル向けに人間に優しい機能を追加しています。
標準JSON
- RFC 8259 / ECMA-404で定義
- コメントなし、末尾カンマなし、文字列はダブルクォート必須
- すべての言語・ランタイムでネイティブサポート
- 最適な用途:APIレスポンス、データストレージ、サービス間通信
JSON5
JSON5はECMAScript 5の構文機能を取り込んでJSONを拡張しています。
// JSON5ではコメントが書ける
{
name: "田中", // クォートなしのキーも可
'greeting': 'こんにちは', // シングルクォートも可
age: 30, // 末尾カンマも可
hex: 0xFF, // 16進数リテラル
infinity: Infinity, // 特殊数値
}
- 適した用途:コメントや緩い構文が欲しい設定ファイル
- 不適切な用途:サービス間のデータ交換(汎用パーサーでは解析不可)
JSONC(コメント付きJSON)
JSONCは // と /* */ コメントを許可しますが、それ以外は標準JSONと同一です。
{
// エディターの設定
"editor.tabSize": 2,
"editor.formatOnSave": true,
/* 全言語に適用される設定 */
"files.autoSave": "onFocusChange"
}
- 利用例:VS Code(
settings.json、launch.json)、TypeScript(tsconfig.json) - サポート:エディターや特定ツールのみ(汎用パーサーでは動作しない)
比較表
| 機能 | JSON | JSON5 | JSONC |
|---|---|---|---|
| コメント | 不可 | 可 | 可 |
| 末尾カンマ | 不可 | 可 | 不可 |
| シングルクォート | 不可 | 可 | 不可 |
| クォートなしキー | 不可 | 可 | 不可 |
| 汎用パーサー対応 | はい | 限定的 | 限定的 |
| 最適な用途 | API・データ | 設定ファイル | エディター設定 |
各言語でのJSON操作
JavaScript / Node.js
JavaScriptにはグローバルの JSON オブジェクトとしてJSON操作が組み込まれています。
// JSON文字列をオブジェクトにパース
const jsonString = '{"name": "田中", "age": 30}';
const user = JSON.parse(jsonString);
console.log(user.name); // "田中"
// オブジェクトをJSON文字列にシリアライズ
const data = { name: "佐藤", scores: [95, 87, 92] };
const pretty = JSON.stringify(data, null, 2); // 2スペースでプリティプリント
const minified = JSON.stringify(data); // ミニファイ
// 安全なパース(エラーハンドリング)
function safeJsonParse(str) {
try {
return { ok: true, data: JSON.parse(str) };
} catch (e) {
return { ok: false, error: e.message };
}
}
JSONを使ったディープクローン(シンプルだが制限あり):
// 単純なオブジェクトには有効だが、関数・undefined・Dateオブジェクトは失われる
const clone = JSON.parse(JSON.stringify(original));
Python
Pythonには標準ライブラリの json モジュールがあります。
import json
# JSON文字列をパース
json_string = '{"name": "田中", "age": 30}'
data = json.loads(json_string)
print(data["name"]) # 田中
# JSON文字列にシリアライズ
user = {"name": "佐藤", "scores": [95, 87, 92]}
pretty = json.dumps(user, indent=2, ensure_ascii=False) # 日本語をそのまま出力
minified = json.dumps(user, separators=(',', ':'))
# ファイルから読み込み
with open("data.json", "r", encoding="utf-8") as f:
config = json.load(f)
# ファイルに書き込み
with open("output.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
Go
Goでは encoding/json パッケージと構造体タグを使ってマッピングします。
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"` // omitemptyはゼロ値をスキップ
}
func main() {
// Unmarshal(パース)
jsonStr := []byte(`{"name":"田中","age":30}`)
var user User
if err := json.Unmarshal(jsonStr, &user); err != nil {
panic(err)
}
fmt.Println(user.Name) // 田中
// Marshal(シリアライズ)
output, _ := json.MarshalIndent(user, "", " ")
fmt.Println(string(output))
// mapへのパース(動的な構造)
var dynamic map[string]interface{}
json.Unmarshal(jsonStr, &dynamic)
}
Java
Javaには組み込みのJSONサポートはありませんが、JacksonやGsonなどのライブラリが広く使われています。
Jackson:
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonExample {
static class User {
public String name;
public int age;
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// デシリアライズ
String json = "{\"name\":\"田中\",\"age\":30}";
User user = mapper.readValue(json, User.class);
System.out.println(user.name); // 田中
// シリアライズ
String output = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(user);
System.out.println(output);
// 汎用マップへのパース
var map = mapper.readValue(json, Map.class);
}
}
Gson(Google):
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
Gson gson = new GsonBuilder().setPrettyPrinting().create();
User user = gson.fromJson(jsonString, User.class);
String output = gson.toJson(user);
JSONのパースとセキュリティ
JSONのパースは一般的に安全ですが、重要なセキュリティ上の注意点があります。
JSONインジェクション
JSONインジェクションは、ユーザーの入力をサニタイズせずに文字列の結合でJSONを組み立てた際に発生します。攻撃者が文字列のコンテキストを破ることができます。
脆弱なパターン:
// 絶対にやってはいけない
const userInput = '", "isAdmin": true, "x": "';
const json = `{"username": "${userInput}", "isAdmin": false}`;
// 生成されるJSON: {"username": "", "isAdmin": true, "x": "", "isAdmin": false}
安全なパターン — 常に JSON.stringify を使う:
// 適切なシリアライズでJSONを組み立てる
const payload = {
username: userInput, // どんな入力も安全にエスケープされる
isAdmin: false
};
const json = JSON.stringify(payload);
プロトタイプ汚染(Prototype Pollution)
JavaScriptでは、一部の安全でないJSONパーサーや手動のオブジェクトマージにより、攻撃者が __proto__ のようなプロパティを注入してアプリケーション内のすべてのオブジェクトに影響を与えることがあります。
// 危険:信頼できないJSONを既存オブジェクトにマージ
const untrusted = JSON.parse('{"__proto__": {"isAdmin": true}}');
Object.assign({}, untrusted); // Object.prototypeを汚染する可能性
// 安全:辞書にはObject.create(null)を使うか、スキーマを検証する
const safe = Object.create(null);
大きなペイロードによるサービス拒否(DoS)
極端に大きいJSONや深くネストされたJSONをパースすると、メモリやCPUを使い果たす可能性があります。
- HTTPサーバーレベルでリクエストボディの最大サイズを設定する(例:ExpressのBody-parserのlimit)
- パース後の構造の深さやサイズを処理前に検証する
- 大きなファイルにはストリーミングパーサーを使用する(後述)
数値の精度
JSONの数値には精度の上限が仕様で定義されていませんが、JavaScriptの JSON.parse はすべての数値をIEEE 754の倍精度浮動小数点に変換します。Number.MAX_SAFE_INTEGER(2^53 - 1)より大きな整数は精度を失います。
// 大きな整数での精度損失
JSON.parse('{"id": 9007199254740993}')
// → {id: 9007199254740992} ← 誤った値!
// 解決策:大きな整数は文字列として扱う
JSON.parse('{"id": "9007199254740993"}')
JSONのパフォーマンスのヒント
本番環境ではJSONをミニファイする
ネットワーク送信前に不要な空白をすべて削除します。典型的なAPIレスポンスで20〜40%のペイロード削減が見込めます。JSONフォーマッターで即座にミニファイできます。
大きなファイルにはストリーミングパーサーを使う
500MBのJSONファイルを一度にメモリに読み込むのは現実的ではありません。ストリーミングパーサーはデータをインクリメンタルに読み込んで処理します。
- Node.js:
stream-json、JSONStream - Python:
ijson - Java: JacksonのストリーミングモードJSONParser
// Node.jsのstream-jsonを使ったストリーミング例
const { parser } = require('stream-json');
const { streamArray } = require('stream-json/streamers/StreamArray');
const fs = require('fs');
fs.createReadStream('large-data.json')
.pipe(parser())
.pipe(streamArray())
.on('data', ({ key, value }) => {
// ファイル全体をロードせずに各アイテムを処理
processItem(value);
});
無駄なシリアライズを避ける
不必要にJSONを再シリアライズ・再パースするのはCPUの無駄遣いです。JSONレスポンスを受け取ってそのまま転送する場合は、パースして再stringifyするのではなく生の文字列を渡しましょう。
より高速なシリアライズライブラリを選ぶ
スループットが重要なアプリケーションには、より高速なJSONライブラリを検討します。
| 言語 | より高速な代替ライブラリ | メモ |
|---|---|---|
| JavaScript | fast-json-stringify、simdjson-js |
大きなペイロードで最大2〜5倍高速 |
| Python | orjson、ujson |
orjsonは日時オブジェクトをネイティブ処理 |
| Java | jsoniter |
単純な型ではJacksonより高速なことが多い |
Gzip圧縮
JSONはキー名の繰り返しが多いため非常に高い圧縮率が得られます。APIレスポンスにgzipを有効にすると、通常70〜90%のサイズ削減が見込め、圧縮のCPUコストをはるかに上回るメリットがあります。
JSONの主な用途
JSONは現代のWeb開発において欠かせない存在です。代表的な用途を紹介します。
- REST API: クライアントとサーバー間のデータ通信で最も広く使われるフォーマット
- 設定ファイル:
package.json、tsconfig.jsonなど、開発ツールの設定に利用 - データストレージ: MongoDBなどのNoSQLデータベースでドキュメント形式として採用
- ログ出力: 構造化ログとしてJSON形式で出力し、解析ツールで処理
- GraphQL: クエリのレスポンスは常にJSONで返される
- WebSocket: リアルタイムメッセージのエンコードにJSONがよく使われる
他のデータ形式との比較
| 特徴 | JSON | YAML | XML | CSV |
|---|---|---|---|---|
| 可読性 | 高い | 非常に高い | やや低い | 高い(表形式) |
| データ型 | 6種 | 豊富 | なし | なし |
| コメント | 不可 | 可能 | 可能 | 不可 |
| ファイルサイズ | 小さい | 小さい | 大きい | 非常に小さい |
| ネスト構造 | 対応 | 対応 | 対応 | 非対応 |
| スキーマサポート | JSON Schema | JSON Schema / YAML Schema | XSD | なし |
| ストリーミング | 可 | 限定的 | 可(SAX) | 可 |
用途に応じて最適なフォーマットを選択することが重要です。フォーマット間の変換にはYAML-JSONコンバーターやCSV-JSONコンバーターが役立ちます。
JSONツールとバリデーター
適切なツールを使うことで、日々の開発でのJSON操作が大幅に効率化されます。
このサイトのオンラインツール
| ツール | できること |
|---|---|
| JSONフォーマッター | JSONの整形・ミニファイ・バリデーション、構文エラーのハイライト |
| YAML-JSONコンバーター | YAMLとJSONの双方向変換 |
| CSV-JSONコンバーター | CSVの表形式データをJSON配列に変換(逆変換も可能) |
エディタープラグイン
主要なエディターには優れたJSONサポートが組み込まれています。
- VS Code: 組み込みのJSONバリデーション・IntelliSense。「JSON Schema Store」拡張機能でスキーマの自動検出も可能
- JetBrains IDE: 組み込みのJSONフォーマッターとスキーマバリデーション
- Vim/Neovim: Mason/LSP経由で
jsonls言語サーバーを使用
コマンドラインツール
- jq: コマンドラインで使える最強のJSONプロセッサー。JSONストリームのフィルタリング・変換・抽出ができます。
# フィールドの抽出
echo '{"name":"田中","age":30}' | jq '.name'
# 配列のフィルタリング
cat users.json | jq '.[] | select(.age > 25)'
# プリティプリント
jq . data.json
# ミニファイ
jq -c . data.json
- fx: ターミナル上のインタラクティブJSONビューアー
- python -m json.tool: 追加インストール不要の手軽な整形ツール
よくある質問(FAQ)
JSONにコメントは書けますか?
書けません。標準のJSON仕様(RFC 8259)はシンプルさと汎用性を保つために意図的にコメントを含めていません。設定ファイルでコメントが必要な場合は、JSONC(VS Codeで使用)またはJSON5を検討してください。APIで交換するデータにはコメントは不要です。
JSONファイルの最大サイズは?
JSON仕様そのものにサイズ制限はありません。実際の制限はJSONを処理するツールやランタイムによって決まります。
- ほとんどのHTTPサーバーはリクエストボディを制限しています(デフォルトは1〜10MB程度)
- ブラウザの
JSON.parseは数百MBのファイルを処理できますが、メインスレッドがブロックされます - 50MBを超えるファイルにはメモリ問題を避けるためストリーミングパーサーを使用してください
JSON.parse で大きな数値の精度が失われるのはなぜですか?
JavaScriptはすべての数値を64ビットIEEE 754浮動小数点で表現しており、2^53 - 1(9,007,199,254,740,991)を超える整数を正確に表現できません。これより大きな整数はパース時に精度を失います。解決策は大きな整数を文字列として送信するか、対応環境では BigInt 型を使うことです。
JSONの null と JavaScriptの undefined の違いは?
JSONには null はありますが undefined という概念はありません。JavaScriptオブジェクトに対して JSON.stringify を呼ぶと、値が undefined のプロパティは完全に省略され、値が null のプロパティは null として含まれます。JSONを通じてデータをやり取りする際のバグの一般的な原因です。
JSON.stringify({ a: null, b: undefined })
// → '{"a":null}' — bは省略される
JSONはJavaScriptのサブセットですか?
ほぼそうですが、完全には違います。古いECMAScript仕様では、特定のUnicode行末文字(U+2028 LINE SEPARATOR と U+2029 PARAGRAPH SEPARATOR)がJSON文字列では有効でもJavaScriptでは構文エラーになっていました。ES2019でこれが修正され、現在JSONはJavaScriptの構文的なサブセットになっています。
JSONで日付はどう扱いますか?
JSONにはネイティブの日付型がありません。標準的な慣行はISO 8601文字列として表現することです:"2026-03-16T10:00:00Z"。パース時は言語に応じて手動でこの文字列を日付オブジェクトに変換する必要があります。Pythonの orjson のように、日付オブジェクトを自動的にシリアライズ・デシリアライズできるライブラリもあります。
Content-Type: application/json とは何ですか?
application/json はHTTPリクエストまたはレスポンスのボディがJSONデータを含むことを示すMIMEタイプ(メディアタイプ)です。HTTPでJSONを送信する際は常に Content-Type: application/json ヘッダーを設定し、受け取る際も確認するようにしてください。
JSONのキーは重複できますか?
JSON仕様ではオブジェクト内のキー名は一意であるべき(SHOULD)とされていますが、重複を禁止してはいません。実際には、パーサーによって重複の扱いが異なります——最後の値を取るもの、最初の値を取るもの、エラーを投げるものがあります。すべての環境で一貫した動作を保証するために、重複キーは避けてください。
まとめ
JSONはシンプルな構文と高い互換性により、Web開発の標準的なデータ交換形式として定着しています。基本構文をしっかり押さえ、JSON Schemaによるバリデーション、JSON5やJSONCの使い分け、セキュリティとパフォーマンスのベストプラクティスを身につけることで、あらゆるプロジェクトでJSONを自信を持って効率的に活用できます。
このサイトの無料ツールを日々の開発に役立ててください。バリデーションと整形にはJSONフォーマッター、フォーマット変換にはYAML-JSONコンバーター、表形式データの操作にはCSV-JSONコンバーターをご活用ください。
