PHP json_encode类私有成员

时间:2011-08-10 04:20:15

标签: php json

我正在尝试JSON编码PHP中的一些对象,但我遇到了一个问题:我想编码由类私有成员保存的数据。 我发现这段代码通过调用一个编码函数来编码这个对象,如:

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

但是,这只适用于我想编码的对象内部不包含其他对象的情况。我怎么能不仅编码“外部”对象,还编码任何作为对象的成员呢?

9 个答案:

答案 0 :(得分:68)

使用私有属性序列化对象的最佳方法是实现\ JsonSerializable接口,然后实现自己的JsonSerialize方法以返回序列化所需的数据。

<?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现在将正确序列化您的对象。

答案 1 :(得分:35)

如果你使用的是PHP 5.4,你可以使用JsonSerializable接口:http://www.php.net/manual/en/class.jsonserializable.php

您只需在类中实现一个jsonSerialize方法,该方法返回您想要编码的内容。

然后当你将对象传递给json_encode时,它将编码jsonSerialize的结果。

答案 2 :(得分:14)

反正。您需要在类中创建公共方法以返回其所有字段json encoded

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

答案 3 :(得分:12)

我认为@ Petah有最好的方法,但这样你就失去了数组或对象的属性。所以我添加了一个递归执行的函数:

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

编辑:在数组循环内添加了is_object()检查,以避免在数组元素不是对象(如字符串或数字)时在下一个extract_props()调用中出现get_class()异常。

答案 4 :(得分:3)

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

    return json_encode($objectArray);
}

我个人认为这是一种做法。它类似于Petah,但它与封装很好地保持一致,因为数组是从对象填充的。

将此函数放在对象中或作为对象使用的特征。尽管如此。

答案 5 :(得分:2)

这将打印一个包含类foo的所有属性(公共,私有和受保护)的JSON:

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

echo json_encode($properties);

它适用于任何环境。

答案 6 :(得分:2)

使用反射,你可以json_encode私人财产,虽然它不被视为最佳做法:

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

输出:

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

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

答案 7 :(得分:1)

您只能在类中编码对象私有成员。但是,作为旁注,json_encode功能不适合你吗? http://php.net/manual/en/function.json-encode.php

答案 8 :(得分:1)

我认为这对于性格的运用可能是一个很好的例子

使用以下向导,我在应用的多个位置实现了jsonSerializable interface,同时保持代码的可管理性

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

那你只需要做

class YourClass implements JsonSerializable 
{
    use JsonSerializeTrait;

    ... normal encapsulated code...
}