PHP json_编码类私有成员

PHP json_编码类私有成员,php,json,Php,Json,我试图用PHP对一些对象进行JSON编码,但我面临一个问题:我想对由类私有成员保存的数据进行编码。 我发现这段代码通过调用一个encode函数对这个对象进行编码,如下所示: public function encodeJSON() { foreach ($this as $key => $value) { $json->$key = $value; } return json_encode($json); } 但是,只有

我试图用PHP对一些对象进行JSON编码,但我面临一个问题:我想对由类私有成员保存的数据进行编码。 我发现这段代码通过调用一个encode函数对这个对象进行编码,如下所示:

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

但是,只有当我想要编码的对象内部不包含其他对象时,这才有效,事实就是这样。我如何不仅对“外部”对象进行编码,而且对作为对象的任何成员进行编码?

无论如何。您需要在类中创建public方法来返回所有json编码的字段

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

只能从类中对对象的私有成员进行编码。不过,作为补充说明,json_enocde函数是否不适合您

如果您使用的是php 5.4,则可以使用JsonSerializable接口:

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


然后,当您将对象传递到json_encode时,它将对jsonSerialize的结果进行编码。

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

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

echo json_encode($properties);

它可以在任何上下文中工作。

序列化具有私有属性的对象的最佳方法是实现\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\u编码,尽管这不是最佳实践:

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

产出:

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

我个人认为这是一种方法。它与Petah的类似,只是它与封装保持一致,因为数组是从对象填充的


将此函数放在对象中或作为对象使用的特征。每个人都有自己的想法。

我认为@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()异常。

我认为这可能是使用Traits的一个很好的例子

使用下面的guist,我在我的应用程序的多个点中实现,同时保持代码的可管理性

那你只需要做

class YourClass implements JsonSerializable 
{
    use JsonSerializeTrait;

    ... normal encapsulated code...
}

要么使用公共方法,要么使用反射。您应该接受答案。是的,它在类上下文中起作用。然而,当一些类成员也是具有私有成员的对象时,我应该如何处理?如果一些字段又有私有变量,这是否有效?我想不会,因为json_encode不能对它们进行递归调用。中的示例代码似乎表明,如果该方法在类中声明,它就可以工作,因为它可以访问其成员。这样做毫无意义-如果需要获取私有变量,上面的Oleg回答很好。对于测试/调试嵌套严重的对象非常有用。非常感谢:)这是我为具有嵌套对象属性的对象找到的第一个答案。这也适用于PHP5.3.3。谢谢+1为了涵盖数组中的值,还需要一个额外的包装器:私有静态函数extract_props_obj_或_array($objectOrArray){if(is_array($objectOrArray)){$result=array();foreach($objectOrArray as$object){$result[]=extract_props($object);}return$result}else{//我们现在知道这不是一个数组…return extract_props_object($objectOrArray);}}我在我的中实现了这个函数。我发现的实现中有一个问题。在调用
$prop->getValue()之前,您必须检查
isset(get_class($object),$name)
或者,如果属性未设置,您会收到PHP通知。
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));
}
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...
}