How to sort JSON data using PHP & usort?
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": 52380开发者_C百科0,
"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.
Few notes:
To use any of the array functions on the
json_decode()
ed data, you must passtrue
as the second parameter which gives you an associative array instead of an object.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.
$array = $json_decode($json,true); //> tradyblix
ksort($array); //> Sort by keys
First off, your json is invalid as you're not placing curly brackets around the associative array that contains 'hours'. This might not be an issue if you've cut it out for brevity, but I had to change it when debugging.
More importantly, you can ask json_decode to convert the data in to an associative array instead of an instance of stdClass. ksort will then allow you to sort by keys.
$json = file_get_contents('jsonsort.txt');
$obj = json_decode($json, true);
var_dump($obj);
ksort($obj['hours']);
var_dump($obj);
You could have sorted by values with sort - usort is not needed unless you need to make a custom comparison function, say, comparing instances of objects.
You can then iterate and emit with this (escaping & markup added):
echo "<ol>\n";
foreach($obj['hours'] as $key => $val) {
echo "\t<li>" . htmlentities($key) . ' => ' . htmlentities($val) . "</li>\n";
}
echo "</ol>\n";
精彩评论