Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/243.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在具有神奇属性的类上进行json_编码_Php_Json - Fatal编程技术网

Php 在具有神奇属性的类上进行json_编码

Php 在具有神奇属性的类上进行json_编码,php,json,Php,Json,我正在尝试使用\u get和\u set对所有具有魔法属性的对象数组进行json\u编码json_encode完全忽略这些属性,导致空对象数组(所有正常属性都是private或protected) 那么,想象一下这个类: class Foo { public function __get($sProperty) { if ($sProperty == 'foo') { return 'bar!'; }

我正在尝试使用
\u get
\u set
对所有具有魔法属性的对象数组进行
json\u编码
json_encode
完全忽略这些属性,导致空对象数组(所有正常属性都是
private
protected

那么,想象一下这个类:

class Foo
{
    public function __get($sProperty)
    {
        if ($sProperty == 'foo')
        {
            return 'bar!';
        }
        return null;
    }
}

$object = new Foo();
echo $object->foo; // echoes "foo"
echo $object->bar; // warning
echo json_encode($object); // "{}"
我已经尝试为类实现了
IteratorAggregate
Serializable
,但是
json_encode
仍然没有看到我的神奇属性。由于我试图对这些对象的数组进行编码,因此类上的
AsJSON()
-方法也无法工作

更新迭代器聚合
不起作用


顺便说一句:最重要的是“动态实体”。魔法属性是否真的存在是关于语义的争论。

这是正确的行为
JSON只能包含数据而不能包含方法-它是独立于语言的,因此编码对象方法没有意义。

您的评论:

我问的是魔法属性,而不是方法维加德·拉森1分钟前

没有魔法属性这样的东西。

您现在拥有的只是一个神奇的方法,当您尝试访问不可见的属性时,会调用该方法

再说一遍

$obj->foo不存在

神奇方法的实现方式与PHP无关,它无法神奇地知道您正在使用神奇方法“神奇地”使其看起来像是有
$obj->foo

如果属性不存在,则在对其进行
json\u编码时将不会将其放入对象中


此外,即使
json\u encode
知道
\u get
处于活动状态,它也不知道使用什么值来调用它。

它怎么知道您的属性

$object = new Foo();
echo $object->foo; // how do you know to access foo and not oof?
                   // how do you expect json_encode to know to access foo?
神奇的方法是语法上的糖分,当你使用它们时,它们大多会回击。这就是一个例子

echo json_encode($object); // "{}"

当然,它是空的,$object没有公共属性,只有一个神奇的方法和随后的语法糖(变酸)

我会在对象上创建一个方法来返回内部数组

class Foo
{
    private $prop = array();

    public function __get($sProperty)
    {
       return $this->prop[$sProperty];
    }

    public function __set($sProperty, $value)
    {
       $this->prop[$sProperty] = $value;
    }

    public function getJson(){
        return json_encode($this->prop);
    }
}



$f = new Foo();
$f->foo = 'bar';
$json = $f->getJson();
json_encode()不会向对象“询问”任何接口。它通过调用obj->get\u properties()直接获取表示对象属性的哈希表指针。然后它在这个哈希表上进行迭代(同样是直接的,没有使用诸如Traversable、Iterator等接口),并处理标记为public的元素。请参见ext/json/json.c中的
static void json\u encode\u array()
这使得json_encode()的结果中不可能显示属性,但不能作为$obj->propname进行访问

编辑:我没有对它进行过太多的测试,忘记了“高性能”,但你可能想从它开始

interface EncoderData {
  public function getData();
}

function json_encode_ex_as_array(array $v) {
  for($i=0; $i<count($v); $i++) {
    if ( !isset($v[$i]) ) {
      return false;
    }
  }
  return true;
}

define('JSON_ENCODE_EX_SCALAR', 0);
define('JSON_ENCODE_EX_ARRAY', 1);
define('JSON_ENCODE_EX_OBJECT', 2);
define('JSON_ENCODE_EX_EncoderDataObject', 3);

function json_encode_ex($v) {
  if ( is_object($v) ) {
    $type = is_a($v, 'EncoderData') ? JSON_ENCODE_EX_EncoderDataObject : JSON_ENCODE_EX_OBJECT;
  }
  else if ( is_array($v) ) {
    $type = json_encode_ex_as_array($v) ? JSON_ENCODE_EX_ARRAY : JSON_ENCODE_EX_OBJECT;
  }
  else {
    $type = JSON_ENCODE_EX_SCALAR;
  }

  switch($type) {
    case JSON_ENCODE_EX_ARRAY: // array [...]
      foreach($v as $value) {
        $rv[] = json_encode_ex($value);
      }
      $rv = '[' . join(',', $rv) . ']';
      break;
    case JSON_ENCODE_EX_OBJECT: // object { .... }
      $rv = array();
      foreach($v as $key=>$value) {
        $rv[] = json_encode((string)$key) . ':' . json_encode_ex($value);
      }
      $rv = '{' . join(',', $rv) .'}';
      break;
    case JSON_ENCODE_EX_EncoderDataObject:
      $rv = json_encode_ex($v->getData());
      break;
    default:
      $rv = json_encode($v);
  }
  return $rv;
}

class Foo implements EncoderData {
  protected $name;
  protected $child;

  public function __construct($name, $child) {
    $this->name = $name;
    $this->child = $child;

  }
  public function getData() {
    return array('foo'=>'bar!', 'name'=>$this->name, 'child'=>$this->child);
  }
}


$data = array();
for($i=0; $i<10; $i++) {
  $root = null;
  foreach( range('a','d') as $name ) {
    $root = new Foo($name, $root);
  }
  $data[] = 'iteration '.$i;
  $data[] = $root;
  $root = new StdClass;
  $root->i = $i;
  $data[] = $root;
}
$json = json_encode_ex($data);
echo $json, "\n\n\n";
$data = json_decode($json);
var_dump($data);

这是一个非常古老的线程,但为了不混淆其他对如何使用魔术方法在PHP中获取/设置属性以及如何影响JSON编码感兴趣的人,我的理解如下

在类中包含uuu get和uuu set方法可以为您提供一个接口来处理给定类的动态命名属性。大多数人定义了一个内部关联数组来执行内务管理

您的foo/bar示例没有出现在JSON编码中的原因是您只是创建了一个返回值的关联。它没有将对象本身的属性设置为该值

如果您做了如下操作:

公共函数集($name,$value){ $this->data[$name]=$value; }

如果你打电话:

$foo=新对象类; $foo->set('foo','bar')

现在在数组$data['foo']='bar'中有一个元素 如果对对象进行json_编码,则表示该关系

json_encode不编码方法,只编码属性。这是没有办法的。对于您的代码,与magic uuu get相当的功能是在构造函数中包含对set的调用,即“硬连线”名为“foo”的属性的值

归根结底,我不知道你在争取什么细节,因为你没有提供太多的细节。但是,对对象或数组进行json_编码只会给出可用属性的列表。如果你必须通过一个解释函数,并且以某种方式依赖于它,那是一个不同的问题,不幸的是我没有答案


我希望这会有所帮助,即使它是降级线程的一部分,讽刺的是,IMO中包含了解决方案。

我发现以下方法对我创建具有动态属性的类并使用json_encode输出它们很有效。也许这有助于其他人


PHP5.4有一个名为
JsonSerializable
的接口。它有一个方法,
jsonSerialize
,它将返回要编码的数据。通过实现它,这个问题很容易解决。

没有魔法属性,只有当您尝试访问未声明的属性时调用的魔法方法。当您尝试对这些对象的数组进行
json\u编码时会发生什么
json\u encode
不知道调用
getJson()
。问题中也提到了这一点。其想法不是使用
json\u编码
。。。。而是调用对象上的getJSON。查看类后的exmaple,正如Chacha102所说,您使用我添加到类中的getJSON方法,这样就知道存在哪些属性,因为它可以访问类内部。我有一个这些对象的数组。在数组中的每个对象上调用
json\u encode
并不是解决这个问题的干净方法。好吧,以您现有的结构,这似乎是唯一的方法
$obj = new StdClass;
$obj->x = new StdClass;
$obj->x->y = $obj;
echo json_encode($obj); // warning: recursion detected...
echo json_encode_ex($obj); // this one runs until it hits the memory limit