How to sort JSON data using PHP & usort?

Joe W picture Joe W · Jun 14, 2011 · Viewed 11.5k times · Source

How might I sort the following using PHP? (where wed_2_open comes after wed_1_close)

I have the following JSON data:

"hours": {
  "mon_1_open": 406800,
  "mon_1_close": 437400,
  "tue_1_open": 493200,
  "tue_1_close": 523800,
  "wed_1_open": 579600,
  "wed_1_close": 590400,
  "thu_1_open": 61200,
  "thu_1_close": 91800,
  "fri_1_open": 147600,
  "fri_1_close": 178200,
  "sat_1_open": 237600,
  "sat_1_close": 264600,
  "sun_1_open": 324000,
  "sun_1_close": 345600,
  "wed_2_open": 597600,
  "wed_2_close": 619200
}

Which I then turn into a usable format using JSON_decode:

$obj=json_decode($json);

This is put into a loop to use convert it to HTML:

foreach ($obj->hours as $key => $val) {
    // Turn array items into HTML list items
}

From previous answers it seems like usort may be an answer, but I get errors telling me $obj is an object rather than an array.

Thanks.

Answer

Salman A picture Salman A · Jun 14, 2011

Few notes:

  1. To use any of the array functions on the json_decode()ed data, you must pass true as the second parameter which gives you an associative array instead of an object.

  2. Whenever you plan to sort an array, look at this page which helps you decide which of the 12+ array sorting functions you should use.

Since the desired sorting is not intuitive (sorting by key puts friday on top and close before open) you should define a custom sorting function; use uksort() which allows you to do just that on array keys:

<?php
$data = json_decode('{"hours": {
    "mon_1_open": 406800,
    "mon_1_close": 437400,
    "tue_1_open": 493200,
    "tue_1_close": 523800,
    "wed_1_open": 579600,
    "wed_1_close": 590400,
    "thu_1_open": 61200,
    "thu_1_close": 91800,
    "fri_1_open": 147600,
    "fri_1_close": 178200,
    "sat_1_open": 237600,
    "sat_1_close": 264600,
    "sun_1_open": 324000,
    "sun_1_close": 345600,
    "wed_2_open": 597600,
    "wed_2_close": 619200
}}', true);

echo 'BEFORE ================================' . PHP_EOL;
print_r($data);

uksort($data['hours'], 'customsort'); 

echo 'AFTER  ================================' . PHP_EOL;
print_r($data);

function customsort($a, $b) {
    $tr_prefix = array(
        'mon' => 1,
        'tue' => 2,
        'wed' => 3,
        'thu' => 4,
        'fri' => 5,
        'sat' => 6,
        'sun' => 7
    );
    $tr_suffix = array(
        'open'  => 1,
        'close' => 2
    );
    $a = strtr(strtr($a, $tr_prefix), $tr_suffix);
    $b = strtr(strtr($b, $tr_prefix), $tr_suffix);
    return strcmp($a, $b);
}

Note: my customsort implementation shown above is vary naive. Improvise if necessary.