2012-10-19 66 views
3

我已经看到了非常类似的问题,但我不能确定他们是否清楚地回答 - 也许我有点紧张,对不起。自定义对象到JSON然后返回到自定义对象?

我想让自己的对象具有方便性(清晰度),称之为CardboardBox()。它不会包含代码,只包含数据。我想将它写入数据库并稍后再读取,但很明显,它在读回时是Object()。所有我能想到的,找出它曾经是是:

  1. 有一个成员变量type我设置为CARDBOARD_BOX
  2. 实例化一个新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

看看JSON.parse和JSON.stringify参数。您可以为每个对象定制回调。 'JSON.parse(obj,fn);函数fn(obj){return obj.type ==='a'?新的A(obj):a;如果我有时间的话,我会写一个正确的答案。抱歉。 –

+0

感谢您的回复。非常感谢,但我现在更加困惑。如果我在'CardboardBox()'中使用函数(fn),那么从'JSON.parse()'返回的是'CarboardBox()'的构造函数。 'obj.type'总是未定义的。我想我错过了一些东西...... – Steve

+0

@Steve:你必须设置'.type',并且你没有正确地使用参数(第一个参数不是'obj',因为建议)。请参阅http://jsfiddle.net/LSUJ9/。 – pimvdb

回答

5

一个可能的解决方案是:

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当一个地方。如果你有多个对象可以在一个范围内实例化,那么第二个解析方法可能更合适。这也将占据JSON中的对象而不是CarboardBox s。

编辑这是一个jsFiddle这个方法在行动。

+0

是的,这几乎是我的解决方案。我只是想知道是否有更好的方法。希望JavaScript有适当的类。猜猜我会结束某种Java Bean类型的事情。 – Steve

+0

它不是JavaScript“没有适当的类”,它是JSON格式不支持自定义对象。所以你不得不解决这个问题,就我所知,这个(或者一个变体)是实现它的唯一方法。即使使用Backbone或某个框架将其抽象出来,它也只是在幕后做类似的事情。 – Chad

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 

这仍然依赖于定制标志切换类型,虽然 - 我不知道有这周围的任何方式。

+0

所有优秀的答案。谢谢。我最终可能会编写我自己的JSON包装器。如果我在反序列化后无法将对象放入正确的类中,代码会变得混乱,并且/或者最终我会在对象上做额外的工作。 – Steve