Using json_encode on objects in PHP (regardless of scope)

PhpJsonScopeRedbean

Php Problem Overview


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.

Php Solutions


Solution 1 - Php

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

Solution 2 - Php

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

Solution 3 - Php

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

Solution 4 - Php

Following code worked for me:

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

Solution 5 - Php

I didn't see this mentioned yet, but beans have a built-in method called getProperties().

So, to use it:

// What bean do we want to get?
$type = 'book';
$id = 13;

// Load the bean
$post = R::load($type,$id);

// Get the properties
$props = $post->getProperties();

// Print the JSON-encoded value
print json_encode($props);

This outputs:

{
    "id": "13",
    "title": "Oliver Twist",
    "author": "Charles Dickens"
}

Now take it a step further. If we have an array of beans...

// An array of beans (just an example)
$series = array($post,$post,$post);

...then we could do the following:

  • Loop through the array with a foreach loop.

  • Replace each element (a bean) with an array of the bean's properties.

So this...

foreach ($series as &$val) {
  $val = $val->getProperties();
}

print json_encode($series);

...outputs this:

[    {        "id": "13",        "title": "Oliver Twist",        "author": "Charles Dickens"    },    {        "id": "13",        "title": "Oliver Twist",        "author": "Charles Dickens"    },    {        "id": "13",        "title": "Oliver Twist",        "author": "Charles Dickens"    }]

Hope this helps!

Solution 6 - Php

I usually include a small function in my objects which allows me to dump to array or json or xml. Something like:

public function exportObj($method = 'a')
{
     if($method == 'j')
     {
         return json_encode(get_object_vars($this));
     }
     else
     {
         return get_object_vars($this);
     }
}

either way, get_object_vars() is probably useful to you.

Solution 7 - Php

$products=R::findAll('products');
$string = rtrim(implode(',', $products), ',');
echo $string;

    

Solution 8 - Php

Here is my way:

function xml2array($xml_data)
{
	$xml_to_array = [];
	
	if(isset($xml_data))
	{
		if(is_iterable($xml_data))
		{
			foreach($xml_data as $key => $value)
			{
				if(is_object($value))
				{
					if(empty((array)$value))
					{
						$value = (string)$value;
					}
					else
					{
						$value = (array)$value;
					}
					$value = xml2array($value);
				}
				$xml_to_array[$key] = $value;
			}
		}
		else
		{
			$xml_to_array = $xml_data;
		}
	}
	
	return $xml_to_array;
}

Solution 9 - Php

for an array of objects, I used something like this, while following the custom method for php < 5.4:

$jsArray=array();

//transaction is an array of the class transaction
//which implements the method to_json

foreach($transactions as $tran)
{
	$jsArray[]=$tran->to_json();
}

echo json_encode($jsArray);

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
QuestionA. RagerView Question on Stackoverflow
Solution 1 - PhpjondavidjohnView Answer on Stackoverflow
Solution 2 - PhpilancoView Answer on Stackoverflow
Solution 3 - PhpGabor de MooijView Answer on Stackoverflow
Solution 4 - Phpuser2944142View Answer on Stackoverflow
Solution 5 - PhpchrisfargenView Answer on Stackoverflow
Solution 6 - PhpPhoenixView Answer on Stackoverflow
Solution 7 - PhpAsahajitView Answer on Stackoverflow
Solution 8 - PhpAndreiView Answer on Stackoverflow
Solution 9 - PhpGregView Answer on Stackoverflow