Alex Guerin
Alex Guerin

Reputation: 2386

JSON object ordering being tampered with by jQuery or Javascript

I have the following JSON data being returned, but for some reason, Javascript or jQuery ajax seems to re-organise the items list. The server returns the data sorted alphabetically by item.title (verified)...

The JSON below is after the ordering has been butchered:

   {
        "count": 3,
        "items": {
            "tardis": {
                "type": 40,
                "title": "Tardis",
                "timeMachine": true,
                "reliable": true
            },
            "stargate": {
                "type": "Milky way gate",
                "title": "Stargate + solar flare",
                "timeMachine": true,
                "reliable": false
            }
        }
    }

Does anyone why the ordering is being tampered with? How can I re-order the items byt the title value?

Upvotes: 0

Views: 252

Answers (3)

Ashwin Krishnamurthy
Ashwin Krishnamurthy

Reputation: 3758

If you read the JSON specification at http://www.json.org/, You'll come across this line - An object is an unordered set of name/value pairs

Hence its not wise to trust the ordering of keys in an object. Declare it as an array and you can have your order.

Upvotes: 1

jfriend00
jfriend00

Reputation: 707436

The keys of an object are not in a defined order. They can be returned in any order once they are put into a javascript object. This is as the language was designed and as specified.

If you want them in a specific order, then you either need the data to be in an array (which is ordered) or you need an ordered index for just the keys that will let you access the keys in a desired order.

Arrays have a consistent order, objects do not.

It looks to me like you may want a data structure that looks like this:

{
    "count": 3,
    "items": [
        { 
            "name": "tardis",
            "type": 40,
            "title": "Tardis",
            "timeMachine": true,
            "reliable": true
        },
            "name": "stargate",
            "type": "Milky way gate",
            "title": "Stargate + solar flare",
            "timeMachine": true,
            "reliable": false
        }
    ]
}

This way, the items are in an array with a specific order: items[0], items[1], etc...

FYI, when you do it this way, you don't need the "count" value because the items array will have items.length.

Without the count value, your whole response could just be the array of objects:

    [
        { 
            "name": "tardis",
            "type": 40,
            "title": "Tardis",
            "timeMachine": true,
            "reliable": true
        },
            "name": "stargate",
            "type": "Milky way gate",
            "title": "Stargate + solar flare",
            "timeMachine": true,
            "reliable": false
        }
    ]

Upvotes: 3

David Hedlund
David Hedlund

Reputation: 129792

Your items object is not an array, but just an object with named members. These members have no inherent order.

For instance, doing a console.log({ your object }) in chrome will yield the properties sorted by the member name, in this case "stargate" and "tardis", in that order. But writing for(k in x.items) console.log(k) for the exact same object, will (in Chrome - again, no reliable specification here) iterate over the objects in the order they were defined, and log "tardis", "stargate".

This ordering is an artifact of how an object is presented, not of the object itself. Use arrays if you want ordering:

{
    "count": 3,
    "items": [
        {
            "key": "stargate",
            "type": "Milky way gate",
            "title": "Stargate + solar flare",
            "timeMachine": true,
            "reliable": false
        },
        {
            "key": "tardis",
            "type": 40,
            "title": "Tardis",
            "timeMachine": true,
            "reliable": true
        }
    ]
}

Upvotes: 5

Related Questions