PHP json_encode class private members

PhpJson

Php Problem Overview


I'm trying to JSON encode some objects in PHP, but I'm facing a problem: I want to encode data which is kept by a class private members. I found this piece of code to encode this object by calling an encode function like:

public function encodeJSON() 
{ 
    foreach ($this as $key => $value) 
    { 
        $json->$key = $value; 
    } 
    return json_encode($json); 
}

However, this only works if the object I want to encode does not contain other objects inside, which is the case. How can I do to encode not only the "outer" object, but encode as well any members that are objects too?

Php Solutions


Solution 1 - Php

The best method to serialize an object with private properties is to implement the \JsonSerializable interface and then implement your own JsonSerialize method to return the data you require to be serialized.

<?php

class Item implements \JsonSerializable
{
    private $var;
    private $var1;
    private $var2;

    public function __construct()
    {
        // ...
    }

    public function jsonSerialize()
    {
        $vars = get_object_vars($this);

        return $vars;
    }
}

json_encode will now serialize your object correctly.

Solution 2 - Php

If you're using php 5.4 you can use the JsonSerializable interface: http://www.php.net/manual/en/class.jsonserializable.php

You just implement a jsonSerialize method in your class which returns whatever you want to be encoded.

Then when you pass your object into json_encode, it'll encode the result of jsonSerialize.

Solution 3 - Php

I think @Petah's got the best approach, but that way you lose properties that are array or object. So I added a function wich do that recursively:

function json_encode_private($object) {
	
	function extract_props($object) {
		$public = [];
		
		$reflection = new ReflectionClass(get_class($object));
		
		foreach ($reflection->getProperties() as $property) {
			$property->setAccessible(true);
			
			$value = $property->getValue($object);
			$name = $property->getName();
			
			if(is_array($value)) {
				$public[$name] = [];
				
				foreach ($value as $item) {
					if (is_object($item)) {
                		$itemArray = extract_props($item);
                		$public[$name][] = $itemArray;
					} else {
                		$public[$name][] = $item;
					}
				}
			} else if(is_object($value)) {
				$public[$name] = extract_props($value);
			} else $public[$name] = $value;
		}
		
		return $public;
	}
	
	return json_encode(extract_props($object));
}

EDIT: Added is_object() check inside the array loop to avoid a get_class() exception in the next extract_props() call when the array elements are not objects, like strings or numbers.

Solution 4 - Php

Anyway. You need create public method in your class to return all their fields json encoded

public function getJSONEncode() {
    return json_encode(get_object_vars($this));
}

Solution 5 - Php

I think this may be a great case for the Usage of Traits

using the below guist I implemented jsonSerializable interface in multiple points of my app while keeping the code manageable

https://gist.github.com/zburgermeiszter/7dc5e65b06bb34a325a0363726fd8e14

trait JsonSerializeTrait
{
	function jsonSerialize()
	{
		$reflect = new \ReflectionClass($this);
		$props   = $reflect->getProperties(\ReflectionProperty::IS_STATIC | \ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_PRIVATE);
				
		$propsIterator = function() use ($props) {
			foreach ($props as $prop) {
				yield $prop->getName() => $this->{$prop->getName()};
			}
		};
		
		return iterator_to_array($propsIterator());
	}
}

then you just have to do

class YourClass implements JsonSerializable 
{
    use JsonSerializeTrait;

    ... normal encapsulated code...
}

Solution 6 - Php

public function jsonSerialize()
{
    $objectArray = [];
    foreach($this as $key => $value) {
        $objectArray[$key] = $value;
    }

    return json_encode($objectArray);
}

I personally think this is a way of doing it. It is similar to Petah's, except It keeps in line with encapsulation well, because the array is populated from the object.

Put this function in either your object or as a trait to be used by your object. To each their own though.

Solution 7 - Php

This would print a JSON with all of the properties (public, private and protected) of class foo:

$reflection = new ReflectionClass('Foo');
$properties = $reflection->getdefaultProperties();

echo json_encode($properties);

It would work from any context.

Solution 8 - Php

You can only encode an object's private members from within the class. As a side note though, does the json_enocde function not work for you? http://php.net/manual/en/function.json-encode.php

Solution 9 - Php

Using reflection you can json_encode private properties, although its not considered best practice:

function json_encode_private($object) {
    $public = [];
    $reflection = new ReflectionClass($object);
    foreach ($reflection->getProperties() as $property) {
        $property->setAccessible(true);
        $public[$property->getName()] = $property->getValue($object);
    }
    return json_encode($public);
}

E.g.

class Foo {
	public $a = 1;
	public $b = 2;
}
class Bar {
	private $c = 3;
	private $d = 4;
}

var_dump(json_encode(new Foo()));
var_dump(json_encode_private(new Bar()));

Outputs:

string(13) "{"a":1,"b":2}"
string(13) "{"c":3,"d":4}"

http://codepad.viper-7.com/nCcKYW

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrrrcassView Question on Stackoverflow
Solution 1 - Phpsamsamm777View Answer on Stackoverflow
Solution 2 - PhplucasView Answer on Stackoverflow
Solution 3 - PhpAndre MedeirosView Answer on Stackoverflow
Solution 4 - PhpOlegView Answer on Stackoverflow
Solution 5 - PhpJonathan DSView Answer on Stackoverflow
Solution 6 - PhpYokerView Answer on Stackoverflow
Solution 7 - PhpEmanuil RusevView Answer on Stackoverflow
Solution 8 - PhpNick ONeillView Answer on Stackoverflow
Solution 9 - PhpPetahView Answer on Stackoverflow