PHP Json_Encode Class Private Members

json_encode an array of objects with private properties

You can use the JsonSerializable type like this:

class Car implements JsonSerializable
{
private $make, $model;

public function jsonSerialize() {
return array($this->make, $this->model);
}
}

var $car = new Car();
echo json_encode($car, JSON_PRETTY_PRINT);

How do I json encode private properties in php?

The entire point of having member variables as private is to prevent them from being visible to any external code (serialize is an exception because the entire object will need to be restored between sessions).

Instead of json_encoding this object, you should perhaps create an interface "encodeable" with a method "encode." This will return a json-encoded string of any of the members required by this object. This gives you additional control because instead of serializing all members, you can choose the ones you want to serialize and even perform operations on them to serialize other data.

Actually you can imlement the JsonSerializable interface which works directly with json_encode.

class MyClass implements \JsonSerializable
{
public function jsonSerialize()
{
return get_object_vars($this);
}
}

$myObject = new MyClass();
echo json_encode($myObject);

Encoding static member of class as JSON in PHP

According to PHP manual:

Static properties cannot be accessed through the object using the arrow operator ->.

That means no

Nevertheless, I came up with the solution utilizing Reflections:

class SomeClass
{
public static $one = 1;
private static $two = 2;
public $three = 3;
private $four = 4;
}

$reflection = new ReflectionClass('SomeClass');
$instance = $reflection->newInstance();
$properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);

$jsonArray = array();

foreach($properties as $property) {
$jsonArray[$property->getName()] = $property->getValue($instance);
}

echo json_encode($jsonArray);

The result is

{"one":1,"three":3}

PHP class instance to JSON

You're just about there. Take a look at get_object_vars in combination with json_encode and you'll have everything you need. Doing:

json_encode(get_object_vars($error));

should return exactly what you're looking for.

The comments brought up get_object_vars respect for visibility, so consider doing something like the following in your class:

public function expose() {
return get_object_vars($this);
}

And then changing the previous suggestion to:

json_encode($error->expose());

That should take care of visibility issues.

PHP Json encode returns empty for an object

"why it is not showing object fields"

...because they are marked private. As soon as they are marked public they will be visible to json_encode().

class TestObject
{
public $obj_id;
public $obj_name;

public function __construct($obj_id, $obj_name)
{
$this->obj_id = $obj_id;
$this->obj_name = $obj_name;
}

public function get_obj_id()
{
return $this->obj_id;
}

public function get_obj_name()
{
return $this->obj_name;
}
}

$obj_1 = new TestObject(1, "testname");
echo json_encode($obj_1);

Output:

{"obj_id":1,"obj_name":"testname"}

Demo: http://sandbox.onlinephpfunctions.com/code/528d3b495cd23c9ffbea424556cd042c486c413c

Alternatively if you need to keep the properties private and still JSON-encode them, there are various techniques you can employ - see PHP json_encode class private members for details.

Using json_encode on objects in PHP (regardless of scope)

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 ) );

Extending json_encode for nested objects

Whilst I believe you would be better off writing a proper export/encode function for each of your classes (which would construct a public object from both private and public values just for encoding - you could be quite clever and use php's reflection ability) - instead - you could make use of the following code:

/// example class B
class TestB {
private $value = 123;
}

/// example class A
class TestA {
private $prop;
public function __construct(){
$this->prop = new TestB();
}
}

function json_encode_private($obj){
/// export the variable to find the privates
$exp = var_export($obj, true);
/// get rid of the __set_state that only works 5.1+
$exp = preg_replace('/[a-z0-9_]+\:\:__set_state\(/i','((object)', $exp);
/// rebuild the object
eval('$enc = json_encode('.$exp.');');
/// return the encoded value
return $enc;
}

echo json_encode_private(new TestA());

/// {"prop":{"value":123}}

So the above should work, but I wouldn't recommend using eval anywhere in php - just because I always hear alarm bells quietly off in the distance :)

update

Just had a thought of what might make this a little safer, rather than using eval you could use create_function which would limit some of its creational powers, or at least the scope of those powers...

function json_encode_private($obj){
$exp = var_export($obj, true);
$exp = preg_replace('/[a-z0-9_]+\:\:__set_state\(/i','((object)', $exp);
$enc = create_function('','return json_encode('.$exp.');');
return $enc();
}

update 2

Had a chance to play around with another way of converting an object with private properties, to an object with public properties - using only a simple function (and no eval). The following would need to be tested on whichever version of PHP you are using as it's behaviour - again - might not be reliable.... due to the weird \0Class Name\0 prefixing in the converted private properties (see comments in code).

For more info on this strange prefixing behaviour:

http://uk3.php.net/language.types.array.php#language.types.array.casting

Anyway, so using a test class:

class RandomClass {
private $var = 123;
private $obj;
public function __construct(){
$this->obj = (object) null;
$this->obj->time = time();
}
}

We can use the following function to convert it to a public object:

function private_to_public( $a ){
/// grab our class, convert our object to array, build our return obj
$c = get_class( $a ); $b = (array) $a; $d = (object) null;
/// step each property in the array and move over to the object
/// usually this would be as simple as casting to an object, however
/// my version of php (5.3) seems to do strange things to private
/// properties when casting to an array... hence the code below:
foreach( $b as $k => $v ){
/// for some reason private methods are prefixed with a \0 character
/// and then the classname, followed by \0 before the actual key value.
/// This must be some kind of internal protection causing private
/// properties to be ignored. \0 is used by some languges to terminate
/// strings (not php though, as far as i'm aware).
if ( ord($k{0}) === 0 ) {
/// trim off the prefixed weirdnesss..?!
$e = substr($k, 1 + strlen($c) + 1);
/// unset the $k var first because it will remember the \0 even
/// if other values are assigned to it later on....?!
unset($k); $k = $e;
}
/// so if we have a key, either public or private - set our value on
/// the destination object.
if ( $k !== '' && $k !== NULL && $k !== FALSE ) {
$d->{$k} = $v;
}
}
return $d;
}

So if we put it all together:

$a = new RandomClass();

echo json_encode( private_to_public( $a ) );

/// {"var":123,"obj":{"time":1349777323}}

Again your best / most reliable bet is to either bespokely code your conversion methods for each class, or create some kind of generalised solution using Class Reflection, but that latter is far more involved, more involved than a StackOverflow answer... at least with the amount of time I have free ;)

further info

The above code will work when trying to access objects from anywhere, the reason for implementing this was because my first attempt was obviously to use the following:

echo json_encode( get_object_vars($a) );

/// you will get {} which isn't what you expect

It seems that if you want to use get_object_vars you have to use it from a context that has access to all the properties, i.e. from inside the class you are exposing:

public function getAllProperties(){
return get_object_vars( $this );
}

So, imagine we'd added the above to the RandomClass definition:

echo json_encode( $a->getAllProperties() );

/// you will get {"var":123,"obj":{"time":1349777323}}

This works because the members of a class have access to all the class's properties public or private.... so as I say, working this way is far far superior; superior, but not always possible.



Related Topics



Leave a reply



Submit