サーバーサイドJSのための、JSONで復元できるモデルクラス *追記あり*
ほとんど自分のためのメモ。
サーバサイドJSを使っているとクライアントにwebsocket経由で渡したりmongodbやnstoreで永続化する際にピュアなJSONとしてデータを宣言しなおす必要があって面倒。
じゃあModelクラス自身が読み込み/書き出しできると嬉しいのでは。
coffee-scriptで書いてみた。
class Model _iparam_ : {} constructor : (data={})-> for k,v of @_iparam_ @[k] = data[k] or @_iparam_[k] toJson : (cls)-> return @toJson(@) if cls is undefined return cls unless cls instanceof Object json = {} for k,v of cls if typeof v is 'function' or k[0] is '_' else if typeof v in ['string','number','boolean'] json[k] = v else if v instanceof Array json[k] = (@toJson(v[i]) for i in [0...v.length]) else if v instanceof Object json[k] = @toJson(v) return json
ルール
継承して_iparam_というプロトタイプに初期化用パラメータを詰め込む(実際のモデルスケルトン)
モデルの引数にインスタンス(JSだからオブジェクトだけど)を作ると元のパラメータが復元される
アンダースコア(_)をプレフィックスに持つ変数は無視
Model#toJsonでJSONに書き出し
サンプル
class A extends Model _iparam_ : x : 1 y : 2 _y : 5 #無視 z : [1,3,5] constructor : (data={})-> super data func : -> # 関数定義してもjson化する際には無視する @x+@y
使う
> a = new A > alt = new A { x: 330 } > console.log alt { x: 330, y: 2, _y: 5, z: [ 1, 3, 5 ] } > console.log alt.toJson() { x: 330, y: 2, z: [ 1, 3, 5 ] }
toJsonしたJSONを引数にモデルクラスを作成すると元のパラメータが復元される
そのままコントローラをmixinしたりして使うと何かと楽
追記
ちょっと改良
undefinedのみスルーするようにしないとfalseや0のとき失敗する
いらないパラメータは_をフラグにするのではなく_ignore_で宣言する
class JsonLoader _init_ : {} _ignore_: {} constructor : (params={})-> for k,v of @_init_ if params[k] is undefined @[k] = @_init_[k] else @[k] = params[k] toJson : (cls)-> return @toJson(@) if cls is undefined return cls unless cls instanceof Object json = {} for k,v of cls if typeof v is 'function' or @_ignore_[k]? else if typeof v in ['string','number','boolean'] json[k] = v else if v instanceof Array json[k] = (@toJson(v[i]) for i in [0...v.length]) else if v instanceof Object json[k] = @toJson(v) return json
サンプル
class MyClass extends JsonLoader _init_ : n : 1 str : 'test' bool : false _ignore_: ng : 0 constructor:(data)-> super data @ng = 0 myclass = new MyClass myclass.toJson() #ngを含まない
実際には別のクラスを参照したりして再ロード時に邪魔になるパラメータが多いということにきづいた。