JSON文字列とオブジェクトの相互変換メモ

Written by shoota

Node.jsの標準メソッドでJSON文字列とオブジェクトの相互変換するときの注意メモ

Node.jsを使ったアプリを作成するときに、APIの返却値としてデータオブジェクトを文字列に変換してレスポンスしたい場合や、外部から取得した文字列をパースしてオブジェクトとしてデータストアにそのまま保存したい場合など、文字列とオブジェクトの相互変換はいろいろな場面で役に立つ。特に、非同期なI/Oを利用した効率的なStream処理は、Node.jsの最大の売りといってもよく、Stream内外で文字列とオブジェクトの相互変換は頻繁に行われる。 そういった処理は、暗黙的に呼び出すことのできるJSON(フォーマットのことではなく、標準実装のオブジェクト名)が持っている変換メソッド、 JSON.stringifyJSON.parse を使うのが一般的かと思うが、その挙動についてちょっと勘違いをしていたのでメモしておく。

テスト用コードを書いてみる

結果をみて考えると当たり前なのだが、関数オブジェクトは文字列に変換されない。 そもそも、JSONはデータコンテナフォーマットであり、ピュアなオブジェクト(とそのネスト)で構成されているので、関数オブジェクトなどのデータ以外のものは格納できない(する意味が無い)。 一方でMongoDBはデータストアでありながら内部的なインタプリタで関数オブジェクトを実行したり、コレクション内に関数オブジェクトを持つ状態で保存したりすることできるので、この辺が覚え違いの原因だった。 「BSONがJSONの拡張であり、JSONに似て非なるデータ形式」ということを肝に銘じておかなくてはならない。

また、 JSON.parseの引数文字列は正しいフォーマットのみを受け付けるようだ。 ブレース括弧を省略する、Keyをダブルクウォートで括らない、などは許されない。こちらは当たり前といえば当たり前なのだが、文字列リテラルを書いた文字列となることに注意する。

40行目以降は相互変換の可逆性をテストしている。 console出力したときに関数オブジェクトが文字列に変換されていないだけで実態はまだ参照されているのか、本当に関数オブジェクトの参照がなくなっているかを試すためだ。 結果、もともとあった関数オブジェクトが無いというエラーが発生したので、文字列化したときに関数オブジェクトは完全に紛失するということがわかる。「データコンテナとしてのJSON」を貫いているということだろう。

まとめ

JSON.strigify()とJSON.parse()で相互変換、可逆変換は可能。 ただし、それぞれの引数と戻り値はJSONの定義に則った形式で記述しなくてはならない。