2011-08-10 97 views
22

我想在JSON编码PHP中的一些对象,但我面临一个问题:我想编码由类私人成员保存的数据。 我发现这段代码通过调用编码功能一样对这个对象进行编码:PHP json_encode类私人成员

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

然而,这仅仅在进行到编码我想要的对象不包含内部的其他对象,这是如此。我怎样才能编码不仅“外部”的对象,但编码以及任何成员也是对象?

+0

或者使用公共方法或使用反射 –

+0

你应该接受一个答案。 – Roman

回答

11

无论如何。你需要在你的类中创建public方法返回的所有领域JSON在类的内部编码

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

这是否工作,如果一些领域反过来有私人变数?我猜它不会,因为json_encode不能被递归调用。 –

+0

http://php.net/manual/en/function.get-object-vars.php中的示例代码似乎显示了它的工作方式,因为它可以访问其成员。 – ymajoros

1

只能编码对象的私有成员。但是,请注意,json_enocde函数不适合你吗? http://php.net/manual/en/function.json-encode.php

+0

是的,从一个类的上下文中起作用。但是,当一些班级成员也是私人成员的对象时,我应该如何继续? – rrrcass

2

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

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

echo json_encode($properties); 

它会从任何方面的工作。

41

序列化与私有属性的对象最好的方法是实现\ 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现在将正确序列化您的对象。

+0

这应该是被接受的答案。 – Roman

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

例如

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

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

    return json_encode($objectArray); 
} 

我个人认为这是做这件事的方式。它与Petah类似,只是它与封装很好地保持一致,因为数组是从对象中填充的。

把这个功能在任一对象或为特质,以你的对象使用。尽管每个人都是自己的。

+0

这样做没有意义 - 如果你需要获得私人股票,Oleg的回答在上面可以正常工作。 –

10

我觉得@佩塔提克瓦的得到了最好的方法,但这样你失去的是数组或对象的属性。所以我增加了一个功能至极做递归:

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()异常()调用,当数组元素是不对象,如字符串或数字。

+0

测试/调试大量嵌套对象非常有用。非常感谢:) – Sobakus

+0

这是我找到的具有属性作为嵌套对象的对象的第一个答案。这也适用于PHP 5.3.3。谢谢。 1 –

+0

也涵盖是数组值,则需要一个另外的包装: 私有静态函数extract_props_obj_or_array($ objectOrArray){ \t \t 如果\t(is_array($ objectOrArray)){ \t \t \t $结果=阵列(); \t \t \t的foreach($ objectOrArray为$对象){ \t \t \t \t $导致[] = extract_props($对象); \t \t \t} \t \t \t return $ result; \t \t \t \t \t \t}其他{// 我们现在知道这是不是一个数组.... \t \t \t回extract_props_object($ objectOrArray); \t \t} \t \t} – jfx