Using json_encode on objects in PHP (regardless of scope)

A. Rager picture A. Rager · Jan 15, 2011 · Viewed 123.1k times · Source

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.

Answer

jondavidjohn picture jondavidjohn · Jan 15, 2011

All the properties of your object are private. aka... not available outside their class's scope.

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()                
        ));
    }
    ...
}

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()
        ];
    }
    ...
}

A more detailed writeup