开发者

Using json_encode on objects in PHP (regardless of scope)

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.


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


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


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


Following code worked for me:

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


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!


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.


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


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


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜