6

Is there any way I can set up PHP objects so that when I try to convert them to JSON, all of their protected properties will be shown?

I have read other answers suggesting I add a toJson() function to the object, but that may not really help me a great lot. In most cases, I have an array of objects and I perform the encode on the array itself.

$array = [
    $object1, $object2, $object3, 5, 'string', $object4
];

return json_encode($array);

Yes, I can loop through this array and call toJson() on every element that has such method, but that just doesn't seem right. Is there a way I can use magic methods to achieve this?

4
  • 1
    I don't think that's possible. You could write a serialiser, which would go through all objects (recursively), use reflection to inspect them and get their properties, write those as new unprotected arrays/objects, and then JSON-encodes them. In the end you'd have something like serialise_to_json([$obj1, ..]), where serialise_to_json contains half a ton of code. I'm sure such libraries already exist. Commented Feb 17, 2015 at 8:27
  • @deceze well that's way too complex for a solution. What I think I will do if it actually turns out to be impossible to set it up automatically is I would just add a method toJson() to my objects which would get their properties internally without the need of reflection Commented Feb 17, 2015 at 8:30
  • 1
    Well, you'd just have to write such a serialiser once instead of writing a method for every class; it's not really that difficult. And again, there are probably libraries already out there. Commented Feb 17, 2015 at 8:48
  • @php_nub_qq It's not too complex. I expect it around 25 lines of code, just start! Tip: Have a look at Reflection.. Btw, adding a toJson() is not possible for all kinds of objects since you can't modify internal classes. An external serializer could work for all kinds of objects Commented Feb 17, 2015 at 9:13

1 Answer 1

9

You can implement the JsonSerializable interface in your classes so you have full control over how it is going to be serialized. You could also create a Trait to prevent copy pasting the serializing method:

<?php

trait JsonSerializer {
    public function jsonSerialize()
    {
        return get_object_vars($this);
    }
}

class Foo implements \JsonSerializable 
{
    protected $foo = 'bar';

    use JsonSerializer;
}

class Bar implements \JsonSerializable 
{
    protected $bar = 'baz';

    use JsonSerializer;   
}

$foo = new Foo;
$bar = new Bar;

var_dump(json_encode([$foo, $bar]));

Alternatively you could use reflection to do what you want:

<?php

class Foo
{
    protected $foo = 'bar';
}

class Bar
{
    protected $bar = 'baz';
}

$foo = new Foo;
$bar = new Bar;

class Seriailzer
{
    public function serialize($toJson)
    {
        $data = [];

        foreach ($toJson as $item) {
            $data[] = $this->serializeItem($item);
        }

        return json_encode($data);
    }

    private function serializeItem($item)
    {
        if (!is_object($item)) {
            return $item;
        }

        return $this->getProperties($item);
    }

    private function getProperties($obj)
    {
        $rc = new ReflectionClass($obj);

        return $rc->getProperties();
    }
}

$serializer = new Seriailzer();

var_dump($serializer->serialize([$foo, $bar]));
Sign up to request clarification or add additional context in comments.

1 Comment

So it turns out that there is some php magic that can be done. Thank you, sir!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.