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

JSON と JavaScript オブジェクトは見た目が似ていますが、いくつかの重要な違いがあります。これらの違いを理解することで、データの変換時に起こりうる問題を回避できます。

構文の違い

JavaScript オブジェクトでは柔軟な記法が許されていますが、JSON はより厳格です。

項目JavaScript オブジェクトJSON
キーのクォート省略可能必須(ダブルクォート)
文字列のクォートシングル・ダブル両方可ダブルクォートのみ
末尾のカンマ許容される禁止
// JavaScript オブジェクト(有効)
const jsObj = {
  name: '田中',
  age: 25,
};

// JSON 文字列(有効)
const jsonStr = '{"name": "田中", "age": 25}';

データ型の違い

JavaScript オブジェクトはあらゆる JavaScript の値を保持できますが、JSON で表現できるのは限られた型のみです。

JavaScript オブジェクトで使える値

文字列、数値、真偽値、null、undefined、関数、Symbol、Date、正規表現、Map、Set など、すべての JavaScript 値を格納できます。

JSON で使える値

文字列、数値、真偽値、null、オブジェクト、配列の6種類のみです。関数や undefined は表現できません。

変換時の挙動

JSON.stringify() で JavaScript オブジェクトを JSON に変換する際、一部の値は失われます。

const original = {
  name: "田中",
  greet: function() { return "Hello"; },
  created: new Date(),
  value: undefined,
  sym: Symbol('test')
};

const json = JSON.stringify(original);
console.log(json);
// '{"name":"田中","created":"2024-01-01T00:00:00.000Z"}'

関数、undefined、Symbol は完全に消え、Date は文字列に変換されています。JSON.parse() で戻しても、元の Date オブジェクトにはなりません。

const parsed = JSON.parse(json);
console.log(typeof parsed.created); // "string"(Date ではない)

参照とコピー

JavaScript オブジェクトは参照型ですが、JSON 変換を経由すると完全に新しいオブジェクトが作られます。

const obj = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(obj));

copy.b.c = 999;
console.log(obj.b.c);  // 2(元のオブジェクトは影響を受けない)

この特性を利用してディープコピーを作ることもできますが、上記の型制限があるため万能ではありません。JSON に変換できない値を含むオブジェクトのコピーには、structuredClone() などを使用するのが適切です。