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


75

我正在尝试将对象列表输出为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)什么?
BoltClock

根据定义,“对象”是不可迭代的。
jondavidjohn 2011年

可迭代的意思是对象实现了IteratorAggregate接口,并且可以通过简单的foreach对其进行迭代。
A. Rager

Answers:



152

对象的所有属性都是私有的。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 <5.4的解决方案

如果确实要序列化私有和受保护的对象属性,则必须Class内部实现一个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()                
        ));
    }
    ...
}

更详细的文章


2
当我将这些对象传递给json_encode()时,它只会输出“ {}”。不幸的是,不必将我的数组定义为关联的。
A. Rager

我相信他在谈论$ a-> properties数组,该数组似乎包含您要查找的数据。因为这是一个私有变量,所以json_encode()将忽略它,并导致json_encode()输出“ {}”,如您所描述的。
cmendoza 2011年

我希望json_encode()能够看到公开的方法来定义某种涉及对象的行为,这些对象没有外部可访问的属性。看来这还不能完成,所以我写了一个函数来递归地处理这些对象列表。
A. Rager


为了完整性,如@Jrgns所述,您可以返回get_object_vars( $this ); 转储所有属性。
pcarvalho

46

在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)位置$result = get_object_vars($this);
Cyber​​Ed

这应该是公认的答案-因为get_object_vars会迭代所有属性,所以可以自动与任何类一起使用。
Nico Westerdale

我不确定PHP或代码中发生了什么变化,但是无论最近我做什么,都 get_object_vars($this)忽略了$ this的范围,并拒绝对对象的私有成员进行内省。当所有成员都是私有成员时,我得到一个空数组结果。我正在使用PHP 5.6.31。get_object_vars($this)认识范围是否有一些要求?
JasonGabler

我认为没有任何改变get_object_vars。总是只返回可访问的属性。因此,当从一个对象内部调用时,您将获得所有私有,而从外部则不会。参见php.net/get_object_vars#example-6296
Lode

4

以下代码为我工作:

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

2

我尚未看到此消息,但是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"
}

现在,再进一步。如果我们有各种各样的豆...

// 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"
    }
]

希望这可以帮助!


1

我通常在我的对象中包含一个小函数,该函数允许我转储到数组或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,但是当我有它们的数组时,效果不佳。
A. Rager

然后,您可以使用类似方法将对象数组转换为数组数组,for each($objArray as $key => $obj){$arrArray[$key] = $obj->export());} json_encode($arrArray);或者可以使用get_object_vars()进行array_map。
凤凰城,

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

0

这是我的方式:

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

-1

对于对象数组,在遵循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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.