13

场景:考虑我有一个 JSON 文档,如下所示:

   {
     "name": "David",
     "age" : 78,
     "NoOfVisits" : 4
   }

问题:我想更改文档中字段的顺序/顺序,比如说我想要ageNoOfVisits然后最后是name

截至目前,我将值存储在临时变量中,删除字段并重新创建相同的字段。由于重新分配不起作用:(

我是通过以下方式做到的:

    temp = doc["age"];
    delete doc['age'];
    doc["age"] = temp;

    temp = doc["NoOfVisits "];
    delete doc['NoOfVisits '];
    doc["NoOfVisits"] = temp;

    temp = doc["name"];
    delete doc['name'];
    doc["name"] = temp;

这样我就可以获得所需的有序 JSON 文档。这个要求很特殊,但我仍然想要一些有效的解决方案

问题:有人可以用有效的方法来帮助实现同样的目标吗?

4

6 回答 6

26

May be you could change this using JSON.stringify()

do like

var json = {     "name": "David",     "age" : 78,     "NoOfVisits" : 4   };
console.log(json);
//outputs - Object {name: "David", age: 78, NoOfVisits: 4}
//change order to NoOfVisits,age,name

var k = JSON.parse(JSON.stringify( json, ["NoOfVisits","age","name"] , 4));
console.log(k);
//outputs - Object {NoOfVisits: 4, age: 78, name: "David"} 

put the key order you want in an array and supply to the function. then parse the result back to json. here is a sample fiddle.

于 2013-05-14T12:35:07.480 回答
8

对象没有特定的顺序。


更新:

ES3 规格

ECMAScript 对象是一个无序的属性集合

ES5 规格

未指定枚举属性的机制和顺序(第一个算法中的步骤 6.a,第二个算法中的步骤 7.a)。

被枚举对象的属性可能在枚举过程中被删除。如果在枚举期间还没有访问过的属性被删除,那么它就不会被访问。如果在枚举过程中向正在枚举的对象添加了新属性,则不能保证在活动枚举中访问新添加的属性。在任何枚举中不能多次访问属性名称。


然而。如果您想依赖 V8 实现顺序。

记住这一点。

当迭代一个对象时,V8 迭代如下

  1. 按升序排列的数值属性。(虽然不能保证)
  2. 按插入顺序排列的非数字属性。

如下例所示

var a = {c:0,1:0,0:0};

a.b = 0;
a[3] = 0;
a[2] = 0;

for(var p in a) { console.log(p)};

给出输出

  1. 0
  2. 1
  3. 2
  4. 3
  5. b
  6. C

如果你想要保证订单...

您被迫使用两个单独的数组(一个用于键,另一个用于值),或者构建一个单一属性对象的数组,等等。

(MDN)

于 2013-05-14T12:00:26.273 回答
4

ECMA-262 没有指定枚举顺序。事实上的标准是匹配插入顺序,V8 也这样做,但有一个例外:V8 不保证数组索引的枚举顺序(即,可以解析为 32 位无符号整数的属性名称)。

您的解决方案是有效的,这是在 node.js 中执行此操作的唯一方法,但您可以直接执行以下操作,而不是删除和插入新属性:

var previous = {
  "name": "David",
  "age" : 78,
  "NoOfVisits" : 4
};

var o = {};
o.age = previous.age;
o.NoOfVisits = previous.NoOfVisits;
o.name = previous.name;

如果只是做,我还没有测试过

var o = {
  age: previous.age,
  NoOfVisits: previous.NoOfVisits,
  name: previous.name
};

也是有效的。

于 2013-05-14T12:07:11.833 回答
4

尽管同意 JS 没有定义对象属性的顺序的所有评论和答案,但我发现自己的问题与您有些相似,因此我将尝试回答您的问题:

  function reorder (order, obj) { 
    typeof order === 'string' && (order = order.split (/\s*,\s*/));
    return order.reduce (function (rslt, prop) {
        rslt[prop] = obj[prop];
        return rslt;   
      }, {});
  }

  reorder ("age,noOfVisits,name", {name: "David", age: 78, noOfVisits: 4});

它还可以用于从对象中复制或提取属性的子集。

注意:我的问题需要按预定义的顺序处理属性,这个函数也提供了这样做的基础。

于 2013-05-14T12:21:37.883 回答
1

就 JSON 而言,没有顺序,不像每个对象都有索引的数组。如果你想要一个特定的顺序,你需要做这样的事情来把它变成一个数组:

var contact = {
 "name": "David",
 "age" : 78,
 "NoOfVisits" : 4
}
var arrcontact=[contact.age, contact.NoOfVisits, contact.name]

但是在这样做时,您错过了 JSON 的要点

于 2013-05-14T12:11:24.127 回答
0

如前所述,JavaScript 对象属性没有保证顺序 (想想看,有一个有意义的顺序吗?)。

如果你真的需要一个订单,你可以使用一个数组:

[{"name" : "Dave"}, {"age" : 78}, {"NoOfVisits" : 4}]

或者:

["Dave", 78, 4] // but here you have no idea what is happening

我不想在我的代码中看到任何这些。所以一个更好的主意是重新考虑你想要达到的目标。

于 2013-05-14T12:06:05.937 回答