假设您获得了这个 JSON 对象:
{ id: 3, name: 'C' }
你怎么知道它是维生素对象还是编程语言对象。我清楚了吗?
在类型化语言中,我们只是从名称中理解对象的性质(Type
对象的)。每个对象都有一个名称。我们如何使用 JSON 实现类似的功能?我们如何为 JSON 对象命名?有什么既定的模式吗?
假设您获得了这个 JSON 对象:
{ id: 3, name: 'C' }
你怎么知道它是维生素对象还是编程语言对象。我清楚了吗?
在类型化语言中,我们只是从名称中理解对象的性质(Type
对象的)。每个对象都有一个名称。我们如何使用 JSON 实现类似的功能?我们如何为 JSON 对象命名?有什么既定的模式吗?
如果您遇到此问题,则表示您的序列化格式未正确定义。您应该始终能够毫无问题地从 JSON 对象反序列化。
有两种选择:
添加类型字段:您无法创建类型化对象,因为有多个类型具有相同的字段名称集。通过添加类型字段,对象的底层类型毫无疑问。使用此选项,您将必须在创建真实对象时完成处理类型字段的过程。
使用上下文来决定对象是什么类型:如果您提交的查询暗示应该只返回一种类型的对象,那么就没有问题。或者,如果可以返回多种类型,则响应格式应按类型对对象进行分组。
{
"states": [ { id: 3, name: 'New York' } ],
"cities": [ { id: 4, name: 'New York' } ]
}
您必须添加一个描述对象类型的字段。这样你就永远不会怀疑类型。以Google 的 Calendar API为例。Google 的日历资源都有一个字段“kind”来描述类型。
日历事件如下所示:
{
"kind": "calendar#event",
"etag": etag,
"id": string,
"created": datetime,
"updated": datetime,
"summary": string,
...
}
日历列表条目,如:
{
"kind": "calendar#calendarListEntry",
"etag": etag,
"id": string,
"summary": string,
"description": string,
"location": string,
...
}
等等
对于从其他地方获取的 JSON,没有办法做到这一点。
如果您可以控制 JSON,那么您可以这样做:
为每个对象添加一个“类型”字段。
定制一个 JSON 函数来处理这个问题。这可以通过两种方式完成,一种安全,一种不安全。
创建一个函数stringifyJSONType()
。这一个像往常一样字符串化,但动态添加了一个类型参数。
function stringifyJSONType(o){
o.type=o.constructor.name;
var s=JSON.stringify(o);
delete o.type; //To be clean and not modify the object.
return s;
}
现在,在“安全”方法中,我们必须为我们期望解析的每种类型创建一个 switch-case。这仅允许某些类型(那些已保存在 switch-case 中的类型)。
function parseJSONType(s){
var o=JSON.parse(s);
switch(o.type){
case "String":
o.__proto__=String;
break;
case "Date":
o.__proto__=Date;
break;
case "City": //Your custom object
o.__proto__=City;
break;
case "State": //Your custom object
o.__proto__=State;
break;
case "Country": //Your custom object
o.__proto__=Country;
break;
/*.... more stuff... */
case "Object":
default:
o.__proto__=Object;
break;
}
delete o.type;
return o;
}
现在,像JSON.parse()
and一样使用这两种方法JSON.stringify()
,它就会起作用。但是对于您想要支持的每种新类型,您都必须添加一个额外的case
.
不是太不安全,只是它使用了邪恶的eval()
方法。这不太好。. 只要没有其他人能够type
向您的 JSON 添加自定义参数,就可以了。
在这里,您使用与stringifyJSONType()
上面相同的方法,但使用不同的解析方法。
function stringifyJSONType(o){
o.type=o.constructor.name;
var s=JSON.stringify(o);
delete o.type; //To be clean and not modify the object.
return s;
}
function parseJSONType(s){
var o=JSON.parse(s);
o.__proto__=eval(o.type);
delete o.type;
return o;
}
这样做的好处是不需要 switch-case 并且很容易扩展到新类型(不需要更改代码)。