この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: JSON
SEOタイトル: JavaScript JSON (stringify / parse) 完全ガイド

この記事の要点
  • JavaScript の JSON オブジェクト: JSON.stringify(obj) / JSON.parse(str)
  • JSON.stringify(obj, null, 2)整形 (Indent 2)
  • Date は ISO 文字列に、undefined / function / Symbol は除外
  • 循環参照TypeErrorreplacer 関数で回避可
  • 拡張仕様: JSON5 (コメント可) / JSONL / NDJSON / JSON Schema / MIME は application/json

JavaScript の JSON オブジェクト

JSON (JavaScript Object Notation) は JavaScript のオブジェクトリテラル表記を元にしたデータ交換フォーマットで、Web API のレスポンスや設定ファイルで圧倒的シェアを誇ります。ブラウザと Node.js には組み込みの JSON グローバルオブジェクトがあり、stringifyparse の 2 メソッドで相互変換できます。

基本: stringify と parse

// オブジェクト → JSON 文字列
const obj = { name: 'Alice', age: 30, tags: ['admin', 'user'] };
const json = JSON.stringify(obj);
// '{"name":"Alice","age":30,"tags":["admin","user"]}'

// JSON 文字列 → オブジェクト
const parsed = JSON.parse(json);
// { name: 'Alice', age: 30, tags: ['admin', 'user'] }

// 整形 (インデント 2 スペース)
JSON.stringify(obj, null, 2);
/*
{
  "name": "Alice",
  "age": 30,
  "tags": [
    "admin",
    "user"
  ]
}
*/

// Tab 文字でインデント
JSON.stringify(obj, null, '\t');

stringify のシグネチャ

JSON.stringify(value, replacer, space)

引数用途
value変換する値 (任意の JS 値)
replacer配列なら含めるキー名リスト、関数なら変換ロジック
spaceインデント (数値 = スペース数、文字列 = リテラル)

replacer の使い方

const data = { name: 'Alice', password: 'secret', age: 30 };

// 1. 配列でキーフィルタ (password を除外)
JSON.stringify(data, ['name', 'age']);
// '{"name":"Alice","age":30}'

// 2. 関数で値変換
JSON.stringify(data, (key, value) => {
    if (key === 'password') return undefined;   // 除外
    if (typeof value === 'string') return value.toUpperCase();
    return value;
});
// '{"name":"ALICE","age":30}'

// 3. BigInt を文字列にして JSON 化 (BigInt は素のまま不可)
const big = { id: 9007199254740993n };
JSON.stringify(big, (key, value) =>
    typeof value === 'bigint' ? value.toString() : value
);
// '{"id":"9007199254740993"}'

parse の reviver

JSON.parse(str, reviver) の第二引数 reviver で復元時の変換:

const json = '{"date":"2026-01-15T10:00:00Z","amount":1500}';

// Date 文字列を Date オブジェクトに復元
const obj = JSON.parse(json, (key, value) => {
    if (key === 'date' && typeof value === 'string') {
        return new Date(value);
    }
    return value;
});
console.log(obj.date instanceof Date);   // true

JSON で扱える型 / 扱えない型

JS の型JSON での扱い
Stringそのまま文字列
Numberそのまま数値 (NaN/Infinity は null に)
Booleanそのまま
nullそのまま
Arrayそのまま配列
Object (plain)そのまま
DateISO 8601 文字列 (toJSON() 内部呼び出し)
undefined★ 除外 / 配列では null
function★ 除外
Symbol★ 除外
BigInt★ TypeError 例外
Map / Set{} 扱い (中身消失)
RegExp{} 扱い
JSON.stringify({
    a: undefined,         // → キー自体消失
    b: () => 1,           // → キー自体消失
    c: Symbol('x'),       // → キー自体消失
    d: new Date(),        // → ISO 文字列
    e: NaN,               // → null
    f: Infinity,          // → null
});
// '{"d":"2026-01-15T10:00:00.000Z","e":null,"f":null}'

// 配列内の undefined は null になる
JSON.stringify([1, undefined, 3]);
// '[1,null,3]'

// BigInt はエラー
JSON.stringify({ id: 1n });
// TypeError: Do not know how to serialize a BigInt

循環参照のエラー

const a = { name: 'a' };
const b = { name: 'b', ref: a };
a.ref = b;     // 循環

JSON.stringify(a);
// TypeError: Converting circular structure to JSON

// 対処: replacer で WeakSet を使い検出
function safeStringify(obj) {
    const seen = new WeakSet();
    return JSON.stringify(obj, (key, value) => {
        if (typeof value === 'object' && value !== null) {
            if (seen.has(value)) return '[Circular]';
            seen.add(value);
        }
        return value;
    });
}
safeStringify(a);
// '{"name":"a","ref":{"name":"b","ref":"[Circular]"}}'

カスタム toJSON() メソッド

クラスに toJSON() を定義すると、JSON.stringify 内部で呼ばれます。Date 型もこの仕組みで ISO 文字列化されています:

class User {
    constructor(name, password) {
        this.name = name;
        this.password = password;   // 機密
    }
    toJSON() {
        return { name: this.name };  // password を含めない
    }
}

JSON.stringify(new User('Alice', 'secret'));
// '{"name":"Alice"}'

// Date は標準で toJSON 持ち
new Date().toJSON();
// '2026-01-15T10:00:00.000Z'

parse の例外処理

function safeParse(str, fallback = null) {
    try {
        return JSON.parse(str);
    } catch (e) {
        console.warn('Invalid JSON:', e.message);
        return fallback;
    }
}

safeParse('{"a":1}');         // { a: 1 }
safeParse('not json');         // null
safeParse('{a:1}');            // null (キーは "..." 必須)
safeParse('{"a":1,}');         // null (末尾カンマ不可)

fetch API との組み合わせ

// GET レスポンスを JSON で受ける
const res = await fetch('/api/users');
const users = await res.json();   // 内部で JSON.parse

// POST ボディに JSON を送る
await fetch('/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'Alice', age: 30 }),
});

// エラーハンドリング付き
async function getJson(url) {
    const res = await fetch(url);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
}

MIME タイプ

MIME用途
application/json標準 (RFC 8259)
application/json; charset=utf-8charset 明示 (本来 UTF-8 規定なので省略可)
application/problem+jsonエラー詳細 (RFC 7807 Problem Details)
application/ld+jsonJSON-LD (SEO / Linked Data)
application/x-ndjsonJSON Lines
application/vnd.api+jsonJSON API 仕様

関連仕様

JSON5

標準 JSON にコメント / 末尾カンマ / シングルクォート / 引用符なしキー等を許容した拡張仕様。設定ファイル向け:

{
    // コメントが書ける
    name: 'Alice',          // キー無引用、シングルクォート
    age: 30,
    tags: [
        'admin',
        'user',            // 末尾カンマ OK
    ],
    /* ブロックコメント */
    pi: 3.14159,
    hex: 0xff,             // 16進数
    inf: Infinity,         // 標準 JSON では不可
}

Babel / VSCode の設定ファイル (.babelrc / tsconfig.json) は実質 JSON5 として扱われます。Node.js では json5 パッケージで読み込み。

JSON Lines (NDJSON)

1 行に 1 JSON、複数行をストリームで処理する形式。ログ・ETL でよく使われる:

{"id":1,"name":"Alice"}
{"id":2,"name":"Bob"}
{"id":3,"name":"Carol"}
// JSONL を行ごとに parse
const lines = text.split('\n').filter(Boolean);
const records = lines.map(line => JSON.parse(line));

// 出力
const out = records.map(r => JSON.stringify(r)).join('\n');

JSON Schema

JSON データの構造を JSON で記述する仕様。API のリクエスト / レスポンス検証に使う:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["name", "age"],
  "properties": {
    "name": { "type": "string", "minLength": 1 },
    "age":  { "type": "integer", "minimum": 0, "maximum": 150 },
    "email": { "type": "string", "format": "email" }
  },
  "additionalProperties": false
}

JS では Ajv ライブラリが主流。OpenAPI / AsyncAPI 仕様の内部でも使われています。

TypeScript の型生成

JSON から TypeScript の型定義を自動生成:

# json-to-ts CLI
npx json-to-ts < user.json > user.d.ts

# QuickType (高機能)
npx quicktype --src-lang json --lang ts user.json > user.ts
// 入力 user.json
// { "name": "Alice", "age": 30, "tags": ["a"] }

// 出力
interface User {
    name: string;
    age:  number;
    tags: string[];
}

// fetch のレスポンスを型付け
const user: User = await fetch('/api/user').then(r => r.json());

FAQ

Q: JSON で改行 / タブを送りたい
A: 文字列内で \n / \t を使います。stringify は自動でエスケープ、parse は復元します。

Q: 日付の扱いがバラバラで困る
A: チームで「ISO 8601 文字列 (Date.toISOString)」に統一が無難。parse 時に new Date(str) で復元。または Luxon / Day.js を併用。

Q: 大きすぎる JSON で遅い
A: ストリームパーサ (stream-json / JSONStream) を使う。または NDJSON にして行単位処理。

Q: 数値精度が落ちる
A: JS Number は 53bit 整数まで。9007199254740993 超は BigInt + replacer で文字列化、json-bigint ライブラリで安全に扱う。

Q: パスワードが意図せず JSON に出てしまう
A: クラスに toJSON() を定義して機密フィールドを除外。または DTO 層で詰め替え。