如何给JSON对象命名?

4

考虑您得到了这个JSON对象:

{ id: 3, name: 'C' }

你如何判断一个对象是维生素对象还是编程语言对象?我说清楚了吗?

在强类型语言中,我们可以从对象的名称中简单地理解对象(对象的Type)的性质。 每个对象都有一个名称。那么我们如何在JSON中实现类似的功能呢?如何为JSON对象命名?有没有已经建立的模式?


可能是{name: 'bla bla', etc ..} - user215054
当然,那是我能想到的最简单的方法。还有其他想法吗?比如创建一个自定义的JSON解析器之类的。 - Saeed Neamati
如果我有三个JSON对象,如{ id: 2, name: 'something' },第一个对象指向一个州,第二个对象指向一个城市,第三个对象指向该城市中的一个商店,我该如何区分它们?不一定需要原型操作。 - Saeed Neamati
http://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/ - user215054
3个回答

6
如果您遇到此问题,说明您的序列化格式未正确定义。您应该始终能够从JSON对象中反序列化而无需任何麻烦。
有两个选项:
添加类型字段:由于存在具有相同字段名称集合的多个类型,因此无法创建带有类型的对象。通过添加类型字段,对象的基础类型就不会有任何问题了。选择这个选项后,在创建真正的对象时,您需要处理类型字段的过程。
使用上下文来确定对象的类型:如果您提交的查询意味着只返回一种类型的对象,则没有问题。或者,如果可能返回多个类型,则响应格式应按类型分组对象。
{
  "states": [ { id: 3, name: 'New York' } ],
  "cities": [ { id: 4, name: 'New York' } ]
}

1
这是JSON的不足之处。前一段时间我问了一个问题比较JSON和XML,现在我发现在这方面,XML更为优越。 - Saeed Neamati
3
@SaeedNeamati:我认为问题的一部分在于,在另一个问题中没有人指出XML标记和JSON花括号是相似的(并且是正确的翻译),但不是等价的。花括号定义了一个字典,你需要给字典提供上下文。同样的效果,如果你在所有响应中使用XML标记item而不是citystate,你将会面临与JSON一样无法提供足够上下文的问题。 - unholysampler
1
如果你从REST API的角度来看,URL本身就是资源的名称或类型。因此,如果你请求的资源名为/states.json,那么你应该合理地认为它是包含州信息的JSON数据类型。 - Spoike

3
你需要添加一个描述对象类型的字段,这样你就可以 永远 不用担心类型问题。例如看看 Google 日历 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,
    ...
}

等等。


1

对于从其他地方获取的JSON,无法进行此操作。

如果您控制JSON,则可以执行以下操作:

  1. 每个对象添加一个“类型”字段。

  2. 定制一个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()JSON.stringify()一样使用这两种方法,它会起作用。但是,对于您想要支持的每种新类型,您都必须添加一个额外的case

不安全的方法

不是太不安全,只是它使用了邪恶的eval()方法。这不太好。 只要没有其他人有能力向您的JSON添加自定义type参数,就可以使用它。

在这里,您使用与上面相同的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,并且可以轻松扩展到新类型(无需进行代码更改)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接