【发布时间】:2010-11-26 05:48:26
【问题描述】:
我正在使用 PHP 读取 JSON 数据,并且该数据包含空对象(如 {})。所以问题是,我必须以不同的方式处理对象为空的情况,但我找不到足够好的方法来进行检查。 empty(get_object_vars(object)) 看起来太吓人而且效率很低。有什么好办法做检查吗?
【问题讨论】:
我正在使用 PHP 读取 JSON 数据,并且该数据包含空对象(如 {})。所以问题是,我必须以不同的方式处理对象为空的情况,但我找不到足够好的方法来进行检查。 empty(get_object_vars(object)) 看起来太吓人而且效率很低。有什么好办法做检查吗?
【问题讨论】:
您要反序列化多少个对象?除非empty(get_object_vars($object)) 或强制转换为数组被证明是一个主要的减速/瓶颈,否则我不会担心 - Greg 的解决方案很好。
不过,我建议在解码 JSON 数据时使用 $associative 标志:
json_decode($data, true)
这会将 JSON 对象解码为普通的旧 PHP 数组,而不是 stdClass 对象。然后您可以使用empty() 检查空对象并创建用户定义类的对象,而不是使用stdClass,从长远来看,这可能是一个好主意。
【讨论】:
您可以将其转换为数组(不幸的是,您无法在调用 empty() 时执行此操作:
$x = (array)$obj;
if (empty($x))
...
或强制转换为数组和count():
if (count((array)$obj))
...
【讨论】:
尝试不使用empty(),即:
get_object_vars($obj) ? TRUE : FALSE;
在PHP docs 上我们可以阅读注释:
在不可访问的对象属性上使用
empty()时,如果声明了__isset(),则将调用重载方法。
这意味着当在具有__get() 方法的对象上使用empty() 时,它将始终返回True。
【讨论】:
我必须判断一个对象是否为空,但我也必须忽略私有和受保护的属性,所以我制作了这个小函数,你可以用它来做到这一点。
function empty_obj(&$object, $ignore_private = true, $ignore_protected = true) {
$obj_name = get_class($object);
$obj = (array)$object;
foreach(array_keys($obj) as $prop) {
$is_private = $is_protected = false;
$prop = preg_replace("/[^\w*]/", '', $prop);
$prop_name = str_replace(array($obj_name, '*'), '', $prop);
if(preg_match("~^$obj_name$prop_name$~", $prop))
$is_private = true;
if(preg_match("~^\*$prop_name$~", $prop))
$is_protected = true;
if(!$is_private || !$is_protected || ($is_private && !$ignore_private) || ($is_protected && !$ignore_protected))
return;
}
return true;
}
【讨论】:
我不确定这是否比强制转换为数组更有效,但我猜想更多。您可以开始循环对象,一旦找到答案并停止循环。
function is_obj_empty($obj){
if( is_null($obj) ){
return true;
}
foreach( $obj as $key => $val ){
return false;
}
return true;
}
【讨论】: