# JSONが対応していない値をJSONに保存する方法 JSONは `NaN` / `Infinity` /` -Infinity` や `Date` 型等に対応していない。 しかし、JavaScriptのJSONは、これらを解消する仕組みを持っている。 それは `JSON.parse` の第二引数の `reviver` と`JSON.stringify` の第二引数の `replacer` だ。 注意が必要なのは、 `Date` 型は `toJSON` メソッドを持つため `replacer` に値が渡る前に文字列になってしまうこと。 これに対応するには `toJSON` メソッドを一時退避してしまえば良い。 これらを上手く駆使すれば、JSONに型を保ったまま値を保存し復元することができる。 こんな感じ。 ```JavaScript var original = { 'nan': NaN, '+inf': Number.POSITIVE_INFINITY, '-inf': Number.NEGATIVE_INFINITY, 'date': new Date(), 'symbol': Symbol.for('key'), } var replacer = function(key, value) { switch (true) { case Number.isNaN(value): return { __extendData__: true, type: 'number', value: 'NaN', }; case Number.POSITIVE_INFINITY === value: return { __extendData__: true, type: 'number', value: 'Infinity', }; case Number.NEGATIVE_INFINITY === value: return { __extendData__: true, type: 'number', value: '-Infinity', }; case value instanceof Date: return { __extendData__: true, type: 'date', value: value.toISOString(), }; case typeof value === 'symbol': return { __extendData__: true, type: 'symbol', value: Symbol.keyFor(value), }; } return value; }; var toJSON = Date.prototype.toJSON; delete Date.prototype.toJSON; var serialized = JSON.stringify(original, replacer); Date.prototype.toJSON = toJSON; var reviver = function(key, value) { if (typeof(value) !== 'object' || !value.__extendData__) { return value; } switch(value.type) { case 'number': switch(value.value) { case 'NaN': return Number.NaN; case 'Infinity': return Number.POSITIVE_INFINITY; case '+Infinity': return Number.POSITIVE_INFINITY; case '-Infinity': return Number.NEGATIVE_INFINITY; } case 'date': return new Date(value.value); case 'symbol': return Symbol.for(value.value); } }; var deserialized = JSON.parse(serialized, reviver); console.log(original); console.log(serialized); console.log(deserialized); ``` ※ 公開当時にあった `function` の部分はセキュリティへの配慮が皆無だったので削除しました。