昨日の記事の続き。
https://blog.sfpgmr.net/entry/2016/06/07/220052
ちょっとしたHackというのは以下のコードなのだが、Date
をJSON.stringify
するときになぜreplacer
でこのようなことをしなければならないのかということについてちょっとメモっておく。
// Hackish way of checking if object is Date (this way it works between execution contexts in node-webkit).
// We can't use value directly because for dates it is already string in this function (date.toJSON was already called), so we use this
if (typeof this[k].getTime === 'function') { return { $$date: this[k].getTime() }; }
こうしている理由であるが、2つあって
- nw.js中の実行コンテキストでも動作させるため
Date
をstringify
した結果はシリアライズされた文字列(ISO-8601)なので、このままだとJSON.parse
したときにDate
に復元されないから
である。この2.については以下に詳細に説明されている。
http://d.hatena.ne.jp/Syunpei/20090907/1252301929
上で書かれている困った仕様というのは2つある。
- JSON文字列からDateを復元できない。
Date
をstringify
すると、ブラウザによって実行結果が異なる。
1.の理由はさておき、実質的にはこの2つの仕様によって、ちょっとしたHackが必要なのだ。
ECMA Script 2015のDate.toJSON
の仕様を見たけど、この仕様は変わっていないようである。
ただ形式がISO-8601ではなく拡張ISO-8601だと書いてあったのがちょっと気になる。というのもこの値をJSON-LDフォーマットで保存しようとしたとき、schema.orgのDate
型はISO-8601形式なので、変換が必要になりそうな気がしたからだ。拡張ISO-8601とISO-8601の違いはミリ秒表記があるかないかである。でそのあたりを調べたらISO-8601形式はBasicとExtendという形式があると書いてあって変換不要だと分かった。よかった。
今のところ安全なのはミリ秒の数値に変換しておくことだ。なのでNeDBはミリ秒に変換して、さらにこの数値がDate
だとわかるように{$$date:(ミリ秒)}
というオブジェクトで格納しているのである。
で、NeDBがserializeした結果なのだけれども、普通のテキストファイルで保存される。1つのレコードはテキストの1行で保存される、つまり行数=レコード数である。またserializeされた結果はJSON形式ではない。汎用的な意味合いでちょっと残念だが、おそらくこれはパフォーマンス面で熟考の末こうなったと思われるので、しょうがないかなと思う。