PHP json_encode 类私有成员

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7005860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 01:47:54  来源:igfitidea点击:

PHP json_encode class private members

phpjson

提问by rrrcass

I'm trying to JSON encode some objects in PHP, but I'm facing a problem: I want to encode data which is kept by a class private members. I found this piece of code to encode this object by calling an encode function like:

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

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

However, this only works if the object I want to encode does not contain other objects inside, which is the case. How can I do to encode not only the "outer" object, but encode as well any members that are objects too?

但是,这仅在我要编码的对象内部不包含其他对象时才有效,就是这种情况。我怎样才能不仅对“外部”对象进行编码,还要对作为对象的任何成员进行编码?

回答by samsamm777

The best method to serialize an object with private properties is to implement the \JsonSerializable interface and then implement your own JsonSerialize method to return the data you require to be serialized.

序列化具有私有属性的对象的最佳方法是实现 \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_encodewill now serialize your object correctly.

json_encode现在将正确序列化您的对象。

回答by lucas

If you're using php 5.4 you can use the JsonSerializable interface: http://www.php.net/manual/en/class.jsonserializable.php

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

You just implement a jsonSerialize method in your class which returns whatever you want to be encoded.

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

Then when you pass your object into json_encode, it'll encode the result of jsonSerialize.

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

回答by Oleg

Anyway. You need create public method in your class to return all their fields json encoded

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

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

回答by Andre Medeiros

I think @Petah's got the best approach, but that way you lose properties that are array or object. So I added a function wich do that recursively:

我认为@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));
}

EDIT:Added is_object() check inside the array loop to avoid a get_class() exception in the next extract_props() call when the array elements are not objects, like strings or numbers.

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

回答by Yoker

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

    return json_encode($objectArray);
}

I personally think this is a way of doing it. It is similar to Petah's, except It keeps in line with encapsulation well, because the array is populated from the object.

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

Put this function in either your object or as a trait to be used by your object. To each their own though.

将此函数放在您的对象中或作为您的对象使用的特征。各有各的。

回答by Jonathan dos Santos

I think this may be a great case for the Usage of Traits

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

using the below guist I implemented jsonSerializable interfacein multiple points of my app while keeping the code manageable

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

https://gist.github.com/zburgermeiszter/7dc5e65b06bb34a325a0363726fd8e14

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

then you just have to do

那么你只需要做

class YourClass implements JsonSerializable 
{
    use JsonSerializeTrait;

    ... normal encapsulated code...
}

回答by Emanuil Rusev

This would print a JSON with all of the properties (public, private and protected) of class foo:

这将打印一个包含 class 的所有属性(public、private 和 protected)的 JSON foo

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

echo json_encode($properties);

It would work from any context.

它适用于任何环境。

回答by Nick ONeill

You can only encode an object's private members from within the class. As a side note though, does the json_enocde function not work for you? http://php.net/manual/en/function.json-encode.php

您只能在类中对对象的私有成员进行编码。不过,作为旁注, json_enocde 函数对您不起作用吗?http://php.net/manual/en/function.json-encode.php

回答by Petah

Using reflection you can json_encodeprivate properties, although its not considered best practice:

使用反射可以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()));

Outputs:

输出:

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

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

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