13

Scenario: Consider I have a JSON documents as follows:

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

Issues: I wanted to change the sequence/order of the fields in the document, say I want age, NoOfVisits & then lastly name.

As of now I am storing the value in temporary variable, deleting the field & recreating the same field. Since the reassignment did not work :(

I did it in following way:

    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;

So that I will get the desired ordered JSON document. This requirement is peculiar kind but still I want some efficient solution

Question: Can someone help out with efficient way to achieve the same?

Amol M Kulkarni
  • 19,000
  • 32
  • 110
  • 158
  • 10
    Does it make any sense? Object properties in JS are not ordered. – VisioN May 14 '13 at 11:57
  • javascript object properties are not ordered – Arun P Johny May 14 '13 at 11:58
  • @VisioN he is considering the order may be because of using for .. in – Prasath K May 14 '13 at 11:59
  • 3
    Straight from [the source](http://json.org/): "An object is an **unordered** set of name/value pairs." (emphasis mine) – Joachim Sauer May 14 '13 at 12:00
  • 1
    @PrasathK Who cares. Object is unordered set anyhow. – VisioN May 14 '13 at 12:00
  • @VisioN for(var key in doc)alert(key); what comes first now...?? – Prasath K May 14 '13 at 12:01
  • 1
    @PrasathK Whatever. Depends on the browser, OS, memory state, etc... – VisioN May 14 '13 at 12:02
  • 1
    @PrasathK if you want to go for order in a for loop, you should probably rather consider an array. Objects are just unordered, and nobody can make them behave differently. – Beat Richartz May 14 '13 at 12:03
  • 1
    Is this the actual object that you are dealing with ? If so, then you can directly access all values like `JSONObj.name, JSONObj.age, JSONObj.NoOfVisits` Why do you want to order it ? – GoodSp33d May 14 '13 at 12:04
  • possible duplicate of [Is the order of fields in a javascript object predictable when looping through them?](http://stackoverflow.com/questions/648139/is-the-order-of-fields-in-a-javascript-object-predictable-when-looping-through-t) – Beat Richartz May 14 '13 at 12:05
  • possible duplicate of [Elements order in a "for (… in …)" loop](http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop) – VisioN May 14 '13 at 12:05

6 Answers6

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.

Mithun Satheesh
  • 25,056
  • 14
  • 73
  • 97
  • Thanks for the tip ! I referenced your answer on some other answers where I didn't find a simple way to solve the similar problem I had. – Benj Aug 25 '17 at 14:44
8

Objects have no specific order.


Update:

ES3 Specs

An ECMAScript object is an unordered collection of properties

ES5 Specs

The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified.

Properties of the object being enumerated may be deleted during enumeration. If a property that has not yet been visited during enumeration is deleted, then it will not be visited. If new properties are added to the object being enumerated during enumeration, the newly added properties are not guaranteed to be visited in the active enumeration. A property name must not be visited more than once in any enumeration.


However. If you want to rely on the V8 implementations order.

Keep this in your mind.

When iterating over an Object, V8 iterates as followed

  1. Numeric properties in ascending order. (Though not guaranteed)
  2. Non-numeric properties in order of insertion.

Shown in following example

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)};

gives the output

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

If you want guarantee order ...

you are forced to either use two separate arrays (one for the keys and the other for the values), or build an array of single-property objects, etc.

(MDN)

Community
  • 1
  • 1
Moritz Roessler
  • 8,014
  • 22
  • 50
  • it's right, so you should not try to reorder it, even if some implementations ensure order. You 'd lose portability. – unludo May 14 '13 at 12:03
  • 1
    Damn this slow internet, mdn reference coming – Moritz Roessler May 14 '13 at 12:03
  • -1: No specific order is actually an order. Node.js objects have an order, the insertion order. Browsers implement that as they want. – Gabriel Llamas May 14 '13 at 12:05
  • 1
    @GabrielLlamas actually most of the implementations preserve an order, an alphabetical for literal instantiation and the inertion order for explicit assigned properties. The point is the standard defines it as unordered, so you shouldn't rely on the order of a specific implementation – Moritz Roessler May 14 '13 at 12:08
  • 1
    I see a node.js tag in the question. V8 objects have an insertion order. – Gabriel Llamas May 14 '13 at 12:09
4

ECMA-262 does not specify enumeration order. The de facto standard is to match insertion order, which V8 also does, but with one exception: V8 gives no guarantees on the enumeration order for array indices (i.e., a property name that can be parsed as a 32-bit unsigned integer).

Your solution is valid, it's the only way to do that in node.js, but instead of deleting and inserting new properties you can directly do:

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

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

I've not tested if simply doing

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

is also valid.

Gabriel Llamas
  • 17,220
  • 24
  • 84
  • 105
4

Despite agreeing with all the comments and answers that JS does not define the order of the properties of an object I find myself with a somewhat similar problem to you and so I will try and answer your question:

  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});

It might also be used for copying or extracting a subset of properties from an object.

Note: my problem entails processing the properties in a predefined order and this function provides the basis for doing that also.

HBP
  • 14,098
  • 4
  • 25
  • 33
1

In terms of JSON, there is no order, unlike an array where every object has an index. if you want a specific order, you will need to do something like this to turn it into an array:

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

But in doing this, you are missing out on the point of JSON

legacy
  • 241
  • 1
  • 18
0

As already noted, JavaScript object properties have no guaranteed order (think of it, does it make any sense to have one?).

If you really need to have an order, you could use an array as:

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

or:

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

I wouldn't want to see any of these in my code. So a better idea is to re-think what you are trying to achieve.

Community
  • 1
  • 1
adrianp
  • 2,289
  • 4
  • 21
  • 43