Summary

Here’s a little thing I didn’t know until today: Some browsers, when they make an AJAX request to a web server that returns JSON data, will do some sorting on that JSON data.

So if you get sent back, say:

{
  "18":"Test 18",
  "17":"Test 17",
  "19":"Test 19",
  "15":"Test 15",
  "16":"Test 16",
  "23":"Test 23"
}

Then browsers may automatically sort this to be:

{
  "15":"Test 15",
  "16":"Test 16",
  "17":"Test 17",
  "18":"Test 18",
  "19":"Test 19",
  "23":"Test 23"
}

Here’s how I found out and what I did about it.

A little plugin

A little while ago I released a plugin on the WordPress repository called Select2 Post Selector. This plugin allows you to put a advanced, searchable, select box into a custom field that lets users select one or more posts (or items from a post type) for the value of that custom field.

It’s kinda hard to explain, but it lets you relate posts and post types together really nicely with some huge benefits for sites with lots of content.

I had a support request for this plugin which said that, despite passing a query to the code to return a list of posts sorted by descending date, the sorting wasn’t working.

It took me a while get around to testing this out and the behaviour was repeatable: the list displayed was a different order to the list retrieved by the query and sent back by the AJAX request.

Diagnosis and fix

I basically used a bit of xdebug and Chrome’s developer tools and the network inspector to work out what was going on.

A Google search turned up articles, as always, on the brilliant Stack Overflow like this one that suggest that the browsers sort the returned data, that I’m not the only person experiencing this, and that, in fact, JSON doesn’t demand any ordering according to the order of things in the JSON, and browsers are allowed to do this if they want to.

My fix, in hindsight, actually assumes that browsers will leave stuff in the order it came out – I’ve removed the numeric ID’s. SO…more work is needed – an explicit ordering and sort should be done!

But for the time being my JSON output now looks like this:

[
  {"id":18,"title":"Test 18"},
  {"id":17,"title":"Test 17"},
  {"id":19,"title":"Test 19"},
  {"id":15,"title":"Test 15"},
  {"id":16,"title":"Test 16"},
  {"id":23,"title":"Test 23"}
]

and, it would seem, because the outer array has no keys, it does not get sorted and maintains its order.

The lesson here is that when doing PHP array to JSON to JavaScript object, do not assume anything about the order!