7

これと非常によく似た質問を見たことがありますが、それらが明確に回答されているかどうかを判断することはできません。

私は自分のオブジェクトの利便性 (および明快さ) を持ちたいと思っていますCardboardBox()。コードは含まれず、データのみが含まれます。これをデータベースに書き込んで後で読み返したいのですが、明らかにObject()読み返しのときの型です。それがかつて何であったかを知るために私が考えることができるのは、次のことだけです。

  1. typeCARDBOARD_BOX に設定したメンバー変数がある
  2. new をインスタンスCarbardBox()化し、(ボックス内の) 関数を使用して、プロパティをObject()新しいCardboardBox()オブジェクトにコピーします。

これを行うより良い方法はありますか?実際のタイプを変更できると確信しています。

function CardboardBox() { 
  this.type = "CARDBOARD_BOX"
  this.name = "No set";
  this.populate = new function(obj) {
    // populate this object with obj properties 
}

var box = new CarboardBox();  // CarboardBox
box.name = "My Box";
send = JSON.stringyfy(box);   
.
.
.
obj = JSON.parse(send);    // Object

if (obj.type == "CARDBOARD_BOX") {
  savedBox = new CardboardBox();
  savedBox.populate(obj);
}

前もって感謝します...スティーブ

[編集] 私のテストコード。

function CardboardBox(n) {
  this.name = n;
}

var box = new CardboardBox("My Box");
send = JSON.stringify(box); // JSON CarboardBox()

obj = JSON.parse(send, function fn(obj) { // Object() returned
  log("OB: "+obj.type);
  return obj.type === 'CardboardBox' ? new CardboardBox(obj) : CardboardBox; 
});     
console.log(obj);

出力は次のとおりです。

OB: undefined utils.js:40
OB: undefined utils.js:40
function CardboardBox(n) {
    this.name = n;
} 
4

2 に答える 2

8

考えられる解決策の 1 つは、次のとおりです。

function CardboardBox(n) {
  if(typeof(n) == 'string') {
    //build from name string
    this.name = n;
  } else {
    //build from object
    this.name = n.name;
  }

  //add in this object's "type" in a place
  //that is unlikely to exist in other JSON strings
  this.__type = 'CardboardBox';
}

var box = new CardboardBox("My Box");
send = JSON.stringify(box), // JSON CarboardBox()
obj = JSON.parse(send, function(key, val) {
  //if this is an object, and is CardboardBox
  if(typeof(val) === 'object' && val.__type === 'CardboardBox')
      return new CardboardBox(val);

  return val;

  //or if your object is in a context (like window), and there are many of
  //them that could be in there, you can do:
  //
  //if(typeof(val) === 'object' && context[val.__type])
  //    return new context[val.__type](val);
});


console.log(obj);

基本的に、json を解析するときに、後で探すことがわかっている場所にオブジェクト タイプを格納します。単一のスコープでインスタンス化できる複数のオブジェクトがある場合は、2 番目の解析メソッドがより適切な場合があります。これにより、s ではない JSON 内のオブジェクトも考慮されますCarboardBox

編集ここでは、このメソッドのjsFiddleが動作しています。

于 2012-10-19T16:42:52.093 に答える
1

全体として、あなたは正しいです。Javascript には、プレーンなオブジェクト以外のものをシリアル化する組み込みの方法がないため、JSON とやり取りしても、逆シリアル化するときに特定のクラスが生成されません。そのため、シリアライゼーション/デシリアライゼーションを自分で行うか、何らかのサポートを提供するライブラリを使用する必要があります。

個人的には、シリアライズとデシリアライズを適切に処理するBackbone.jsがこの問題で気に入っています。モデル クラスを定義します。これには、そのデータをシリアル化された形式でサーバーに保存するメソッドと、データを逆シリアル化してモデルに戻すメソッドが含まれます。ここでの重要な設計上の問題は、逆シリアル化先のモデルを認識して逆シリアル化が実行されることです。

  • myModel.fetch()モデル ID に基づいてサーバーからデータを取得するために呼び出すか、または
  • 一連の新しいデータをモデル コンストラクターに渡します: new Model(serializedData)、または
  • 複数のモデルのデータの配列を、モデル タイプを認識しているコレクションに渡しますnew ModelCollection(arrayOfSerializedData)

Backbone が行っていないのは、未知の型の型キャスト データの処理です。私がこれに対処したとき、私は通常@Chadの応答に似た何かをしましたが、仲介者を使用しました。これをプロキシ モデルまたはファクトリとして見ることができます。

var classes = {
    CardboardBox: ...,
    AluminumBox: ...
}

function Deserializer(json) {
    // parse if you're actually dealing with a string
    var data = JSON.parse(json),
        // now look for some custom type flag - you'll need to set this yourself
        type = data.type,
        // class lookup, perhaps with a default
        Cls = classes[type] || DefaultType;
    return new Cls(data);
}

var obj = new Deserializer(send);
obj instanceof CardboardBox; // should work

ただし、これはまだカスタムフラグに依存してタイプを切り替えています-これを回避する方法があるかどうかはわかりません。

于 2012-10-19T16:56:43.413 に答える