Using json_encode on objects in PHP (regardless of scope)
I'm trying to output lists of objects as json and would like to know if there's a way to make objects usable to json_encode
? The code I've got looks something like
$related = $user->getRelatedUsers();
echo json_encode($related);
Right now, I'm just iterating through the array of users and individually exporting them into arrays for json_encode
to turn into usable json for me. I've already tried making the objects iterable, but json_encode
just seems to skip them anyway.
edit: here's the var_dump();
php > var_dump($a);
object(RedBean_OODBBean)#14 (2) {
["properties":"RedBean_OODBBean":private]=>
array(11) {
["id"]=>
string(5) "17972"
["pk_UniversalID"]=>
string(5) "18830"
["UniversalIdentity"]=>
string(1) "1"
["UniversalUserName"]=>
string(9) "showforce"
["UniversalPassword"]=>
string(32) ""
["UniversalDomain"]=>
string(1) "0"
["UniversalCrunchBase"]=>
string(1) "0"
["isApproved"]=>
string(1) "0"
["accountHash"]=>
string(32) ""
["CurrentEvent"]=>
string(4) "1204"
["userType"]=>
string(7) "company"
}
["__info":"RedBean_OODBBean":private]=>
array(4) {
["type"]=>
string(4) "user"
["sys"]=>
array(1) {
["idfield"]=>
string(2) "id"
}
["tainted"]=>
bool(false)
["model"]=>
object(Model_User)#16 (1) {
["bean":protected]=>
*RECURSION*
}
}
}
and here's what json_encode gives me:
php > echo json_encode($a);
{}
I ended up with just this:
function json_encode_objs($item){
if(!is_array($item) && !is_object($item)){
return json_encode($item);
}else{
$pieces = array();
foreach($item as $k=>$v){
$pieces[] = "\"$k\":".json_encode_objs($v);
}
return '{'.implode(',',$pieces).'}';
}
}
It takes arrays full of those objects or just single instances and turns them into json - I use it instead of json_encode. I'm sure there are places I could make it better, but I was hoping that json_encode would be able to detect when to iterate through an object based on its exposed interfaces.
All the properties of your object are private. aka... not available outside their class's scope.
Solution for PHP >= 5.4
Use the new JsonSerializable
Interface to provide your own json representation to be used by json_encode
class Thing implements JsonSerializable {
...
public function jsonSerialize() {
return [
'something' => $this->something,
'protected_something' => $this->get_protected_something(),
'private_something' => $this->get_private_something()
];
}
...
}
Solution for PHP < 5.4
If you do want to serialize your private and protected object properties, you have to implement a JSON encoding function inside your Class that utilizes json_encode()
on a data structure you create for this purpose.
class Thing {
...
public function to_json() {
return json_encode(array(
'something' => $this->something,
'protected_something' => $this->get_protected_something(),
'private_something' => $this->get_private_something()
));
}
...
}
A more detailed writeup
In PHP >= 5.4.0 there is a new interface for serializing objects to JSON : JsonSerializable
Just implement the interface in your object and define a JsonSerializable
method which will be called when you use json_encode
.
So the solution for PHP >= 5.4.0 should look something like this:
class JsonObject implements JsonSerializable
{
// properties
// function called when encoded with json_encode
public function jsonSerialize()
{
return get_object_vars($this);
}
}
In RedBeanPHP 2.0 there is a mass-export function which turns an entire collection of beans into arrays. This works with the JSON encoder..
json_encode( R::exportAll( $beans ) );
Following code worked for me:
public function jsonSerialize()
{
return get_object_vars($this);
}