在 PHP 中的对象上使用 json_encode(无论范围如何)

Posted

技术标签:

【中文标题】在 PHP 中的对象上使用 json_encode(无论范围如何)【英文标题】:Using json_encode on objects in PHP (regardless of scope) 【发布时间】:2011-06-09 12:27:33 【问题描述】:

我正在尝试将对象列表输出为 json,并想知道是否有办法使对象可用于json_encode?我得到的代码看起来像

$related = $user->getRelatedUsers();
echo json_encode($related);

现在,我只是遍历用户数组并将它们单独导出到数组中以供json_encode 转换为对我来说可用的 json。我已经尝试过使对象可迭代,但json_encode 似乎还是跳过了它们。

编辑:这里是 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*
    
  

这是 json_encode 给我的:

php > echo json_encode($a);

我最终得到了这个:

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

它将包含这些对象的数组或仅单个实例转换为 json - 我使用它而不是 json_encode。我确信有些地方我可以做得更好,但我希望 json_encode 能够检测到何时根据其暴露的接口迭代对象。

【问题讨论】:

var_dump($related)echo json_encode($related) 的输出是什么? 'objects' 根据定义是不可迭代的。 通过迭代,我的意思是对象实现接口 IteratorAggregate 并且我可以用简单的 foreach 迭代它们。 【参考方案1】:

对象的所有属性都是私有的。 aka... 在他们的课程范围之外不可用。

PHP 解决方案 >= 5.4

使用新的 JsonSerializable 接口提供您自己的 json 表示以供 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()
        ];
    
    ...

PHP

如果您确实想要序列化您的私有和受保护对象属性,您必须在您的类中实现一个 JSON 编码函数,该函数在您为此创建的数据结构上使用json_encode()

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

【讨论】:

当我将这些对象传递给 json_encode() 时,它只是在输出“”。不幸的是,这不是让我的数组被定义为关联的问题。 我相信他在谈论 $a->properties 数组,它看起来像是包含您所追求的数据。因为这是一个私有变量,它将被 json_encode() 忽略,并导致 json_encode() 输出您所描述的“”。 我希望 json_encode() 能够看到公开的方法来定义某种涉及没有外部可访问属性的对象的行为。似乎这还不能完成,所以我写了一个函数来递归处理这些对象列表。 你可以在jrgns.net/content/…看到另一个解决方案 为了完整起见,正如@Jrgns 所述,您可以返回get_object_vars( $this ); 以转储所有属性。【参考方案2】:

在 PHP >= 5.4.0 中有一个用于将对象序列化为 JSON 的新接口:JsonSerializable

只需在您的对象中实现接口并定义一个JsonSerializable 方法,当您使用json_encode 时将调用该方法。

所以 PHP >= 5.4.0 的 解决方案 应该如下所示:

class JsonObject implements JsonSerializable

    // properties

    // function called when encoded with json_encode
    public function jsonSerialize()
    
        return get_object_vars($this);
    

【讨论】:

要回显 JSON 数组,返回 json_encode($result) where $result = get_object_vars($this); 这应该是公认的答案 - 自动适用于任何类,因为 get_object_vars 将迭代所有属性。 我不确定 PHP 或我的代码发生了什么变化,但无论我最近做什么get_object_vars($this) 都忽略了 $this 的范围并拒绝对对象的私有成员进行内省。当所有成员都是私有的时,我得到一个空数组结果。我正在使用 PHP 5.6.31。让get_object_vars($this) 识别范围有什么要求吗? 我认为get_object_vars 没有任何改变。它总是只返回可访问的属性。因此,当从对象内部调用时,您将获得所有私有数据,而从外部调用则不会。见php.net/get_object_vars#example-6296【参考方案3】:

在 RedBeanPHP 2.0 中有一个批量导出功能,可以将整个 bean 集合转换为数组。这适用于 JSON 编码器..

json_encode( R::exportAll( $beans ) );

【讨论】:

另外,在 RB 2.0 中,如果您将 bean 转换为字符串,您将获得 JSON 表示。【参考方案4】:

以下代码对我有用:

public function jsonSerialize()

    return get_object_vars($this);

【讨论】:

【参考方案5】:

我还没有看到这个,但是 bean 有一个名为 getProperties() 的内置方法。

所以,使用它:

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

这个输出:


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

现在更进一步。如果我们有一个 bean 数组...

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

...那么我们可以执行以下操作:

使用foreach 循环遍历数组。

将每个元素(一个 bean)替换为 bean 属性的数组。

所以这个...

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


print json_encode($series);

...输出这个:

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

希望这会有所帮助!

【讨论】:

【参考方案6】:

我通常在我的对象中包含一个小函数,它允许我转储到数组或 json 或 xml。比如:

public function exportObj($method = 'a')

     if($method == 'j')
     
         return json_encode(get_object_vars($this));
     
     else
     
         return get_object_vars($this);
     

不管怎样,get_object_vars() 可能对你有用。

【讨论】:

我可以使用 json_encode($thing->export());给我我想要的 json,但是当我有它们的数组时,它就不起作用了。 然后您可以将对象数组转换为具有类似for each($objArray as $key => $obj)$arrArray[$key] = $obj->export()); json_encode($arrArray); 的数组的数组,或者您可以使用 get_object_vars() 执行 array_map。【参考方案7】:

这是我的方式:

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;

【讨论】:

【参考方案8】:
$products=R::findAll('products');
$string = rtrim(implode(',', $products), ',');
echo $string;

【讨论】:

【参考方案9】:

对于一个对象数组,我使用了类似的东西,同时遵循 php

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

【讨论】:

以上是关于在 PHP 中的对象上使用 json_encode(无论范围如何)的主要内容,如果未能解决你的问题,请参考以下文章

php中的json_encode()和json_decode()函数的一些说明

PHP的json_encode()函数与JSON对象

多维数组上的 json_encode() - 带有字符串键

PHP json_encode转换空数组为对象

PHP json_encode将行作为对象而不是数组返回[重复]

PHP中json_encode()使用须知,JSON数组和JSON对象