反序列化JavaScript对象实例

问题描述:

我正在研究一个大量使用JavaScript的应用程序。我试图包含一些面向对象的做法。在这种尝试中,我创建了一个基本的类像这样:反序列化JavaScript对象实例

function Item() { this.init(); } 
Item.prototype = { 
    init: function() { 
    this.data = { 
     id: 0, 
     name: "", 
     description: ""  
    } 
    }, 

    save: function() { 
    alert("Saving..."); 
    $.ajax({ 
     url: getUrl(), 
     type: "POST", 
     data: JSON.stringify(this.data), 
     contentType: "application/json" 
    }); 
    } 
} 

我在我的应用程序创建项目实例,然后将它们保存到本地存储像这样:

Item item = new Item(); 
window.localStorage.setItem("itemKey", JSON.stringify(item)); 

在另一页,或在另一次,我正在从这样的本地存储回收该项目:

var item = window.localStorage.getItem("itemKey"); 
item = JSON.parse(item); 
item.save(); 

不幸的是,“保存”功能似乎没有达到。在控制台窗口中,有一个错误,指出:

* save_Click (匿名函数) 的onclick *

我有一种预感,在“(匿名函数)”是说的控制台窗口的方式“调用item.save(),但项目是一个匿名类型,所以我试图访问一个匿名函数“。我的问题是,我不知道如何再次将“var item”转换为Item类实例。有人可以告诉我吗?

+0

试图模仿古典模式而不仅仅是使用原型模式有什么特别的理由吗? – 2012-04-27 12:45:30

+0

我不知道“原型”模式是什么。 – 2012-04-27 14:57:11

+0

是的,我的坏。我其实是想说原型继承习语。 – 2012-04-27 19:17:11

简短的回答:

功能无法序列化成JSON。

说明:

JSON是基于JS文字语法的一个子集跨平台的序列化方案。情况就是这样,它只能存储某些东西。每个http://www.json.org/

  • 对象:一个对象是无序的一组名称/值对。一个对象以{(左大括号)开始并以}(右大括号)结束。每个名称后跟:(冒号),名称/值对由(逗号)分隔。
  • 数组:数组是数值的有序集合。数组以[(左括号)开始,以[]结尾(右括号)。值由(逗号)分隔。
  • 值:值可以是双引号或数字,或者true或false或null,或者对象或数组中的字符串。这些结构可以嵌套。

函数无法序列化为JSON,因为另一个非JS平台将无法反序列化并使用它。请考虑相反的例子。假设我在我的服务器上有一个包含属性和方法的PHP对象。如果我使用PHP的json_encode()对该对象进行序列化,并且方法包含在输出中,那么我的JavaScript如何能够解析和理解方法中的PHP代码,更不用说使用这些方法了?

您在生成的JSON中看到的内容是您所使用平台上功能的toString()值。对于序列化的任何不适合JSON的内容,JSON serilizer将调用toString()

我相信你的解决方案是停止在JSON /本地存储中存储实例。相反,保存您需要时重新设置为新实例的实例的相关数据。

+0

OP没有[尝试]存储实例,也没有任何功能。他只想知道如何从他的数据中重新实例化一个项目。 – Bergi 2012-04-27 14:33:04

+1

@Bergi根本不是真的。她明确指出她拥有一个带有方法的对象实例,试图对JSON序列化,然后将其反序列化,并在非序列化方面丢失了方法。我提出的解决方案可能没有完全解决如何将JS对象序列化为方法,但我清楚地说明了她的方法有什么问题,并提出了我认为是更好的方法。 – JAAulde 2012-04-27 14:47:04

+0

啊,我明白了。我曾看过ajax函数。 – Bergi 2012-04-27 14:56:30

您只能在DOMstorage(cookie,urlparams ...,需要通过JSON.stringify/JSON.parse需要[de]序列化的所有东西)中存储普通对象。所以当你发送ajax数据时你做了什么

ajaxsend(this.data); 

也适用于字符串序列化。您只能存储数据,而不是实例属性(如原型,构造函数等)。所以使用

savestring(JSON.stringify(item.data)); 

这是可能的,因为item.data是这样一个普通的对象。当恢复它时,你只会得到那个普通的数据对象。你的情况很容易重建从纯数据的Item实例,因为你的项目在公共区域提供物业持有它们的值(仅):

var item = new Item; 
item.data = JSON.parse(getjsonstring()); 

你不能做到这一点,怎么也可以javascript可能知道项目有保存功能? json不允许函数作为数据。只是阅读json规范,你不能保存函数。

你需要做的是在你想要存储的哈希中创建一个序列化和反序列化方法。这将指定要导出的内容以及在解析相应的json字符串后如何“唤醒”对象。

免责声明

不是全职的时间J.S.开发人员,答案可能有一些小错误:

的冗长的解释

正如@JAAulde提到的,你不能将对象序列化为JSON,因为具有的功能,您使用的是不允许的技术它。

许多人忘记或忽略在应用程序中使用的对象可能与从存储器中保存/恢复的对象不完全相同。

短&快速回答

既然你已经在你的对象的数据成员封装成一个单一的领域, 你可能想尝试这样的事:

// create J.S. object from prototype 
Item item = new Item(); 

// assign values as you app. logic requires 
item.data.name = "John Doe"; 
item.data.description = "Cool developer, office ladies, love him"; 

// encoded item into a JSON style string, not stored yet 
var encodedItem = JSON.stringify(item.data) 

// store string as a JSON string 
window.localStorage.setItem("itemKey", encodedItem); 

// do several stuff 

// recover item from storage as JSON encoded string 
var encodedItem = window.localStorage.getItem("itemKey"); 

// transform into J.S. object 
item.data = JSON.parse(encodedItem); 

// do other stuff 

干杯。

我知道这个问题已经回答了,但是我偶然偶然发现了这个问题,并且想分享一个解决这个问题的方法,如果有人感兴趣的话。

,而不是这样做:

var item = window.localStorage.getItem("itemKey"); 
item = JSON.parse(item); 
item.save(); 

做这样的事情:

// get serialized JSON 
var itemData = window.localStorage.getItem("itemKey"); 
//instantiate new Item object 
var item = new Item(); 
// extend item with data 
$.extend(item, JSON.parse(itemData)); 

// this should now work 
item.save(); 

这将工作,只要你想调用的函数(即,保存())为原型而不是实例方法(通常是这种情况,OP的原始问题的确是这种情况。

$.extend方法是一种jQuery的实用方法,但它是微不足道的滚动自己的。