When creating a object in php used to return JSON is it possible to add a property and force it to go at the top? I'd like this since the object is exposed via an API and it is nice to have ids at the top.
For example:
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
When you json_encode()
this, it turns into:
{
"name": "John",
"age": 26,
"id": 3645
}
Is there a way to force id
at the top of the object even though it is added last? Note, I can't simply just add id
before adding name
and age
because of other dependent code.
Hmm, nice question!
It is not possible to add a property and force it to go at the top. You have to sort the object properties or the array keys.
Some nitpicking here: JSON is unordered by definition, but the browsers respect the insertion order. More: https://code.google.com/p/v8/issues/detail?id=164
JSON 4.3.3 Object An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.
Check this out: http://ideone.com/Hb4rGQ
<?php
function array_reorder_keys($array, $keynames){
if(empty($array) || !is_array($array) || empty($keynames)) return;
if(!is_array($keynames)) $keynames = explode(',',$keynames);
if(!empty($keynames)) $keynames = array_reverse($keynames);
foreach($keynames as $n){
if(array_key_exists($n, $array)){
$newarray = array($n=>$array[$n]); //copy the node before unsetting
unset($array[$n]); //remove the node
$array = $newarray + array_filter($array); //combine copy with filtered array
}
}
return $array;
}
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
function get_json_sorted($object, $array) {
return json_encode(array_reorder_keys(get_object_vars($object), $array));
}
var_dump(get_json_sorted($obj, array('id', 'name', 'age')));
Not very elegant but...
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
$name = $obj->name;
$age = $obj->age;
unset($obj->name);
unset($obj->age);
$obj->name = $name;
$obj->age = $age;
echo json_encode($obj);
It's easily possible if you use an associative array instead of an object, i.e.
$x = ['name' => 'john', 'age' => 26]; // or: $x = (array)$obj
$x = ['id' => 123] + $x;
echo json_encode($x);
// {"id":123,"name":"john","age":26}
However, it's important to note that in JSON property ordering is not defined and should not be relied upon. If what you currently have works, this change would be rather useless in fact.
This is a solution. Turn the object into an assoc array. Get the last item (both key and value) off of the array (I'm assuming id
is the last element) and move it to the front. Finally convert the assoc array back into an object.
$data_array = json_decode(json_encode($obj), true);
if(is_array($data_array)) {
end($data_array);
$data_array = array_merge(array(key($data_array) => array_pop($data_array)), $data_array);
$data = json_decode(json_encode($data_array), false);
}