Как проверить, является ли объект JSON пустым в PHP?

Я читаю данные JSON с PHP и эти данные содержат пустые объекты (например, {}). Поэтому проблема заключается в том, что я должен обрабатывать случай, когда объект пуст по-разному, но я не могу найти достаточно хороший способ сделать проверку. empty(get_object_vars(object)) выглядит слишком страшно и очень неэффективно. Есть ли хороший способ сделать чек?

Ответ 1

Сколько объектов вы несериализуете? Если empty(get_object_vars($object)) или литье в массив окажется основным замедлением/узким местом, я бы не стал беспокоиться об этом - решение Грега просто отлично.

Я бы предложил использовать флаг $associative при декодировании данных JSON, хотя:

json_decode($data, true)

Это расшифровывает объекты JSON как простые старые массивы PHP, а не как объекты stdClass. Затем вы можете проверить пустые объекты с помощью empty() и создать объекты пользовательского класса вместо использования stdClass, что, вероятно, является хорошей идеей в конечном итоге.

Ответ 2

Вы можете применить его к массиву (к сожалению, вы не можете сделать это при вызове empty():

$x = (array)$obj;
if (empty($x))
    ...

Или применить к массиву и count():

if (count((array)$obj))
    ...

Ответ 3

Попробуйте без использования empty(), который:

get_object_vars($obj) ? TRUE : FALSE;

В PHP docs мы можем прочитать примечание:

При использовании empty() на недоступных объектных свойствах, будет объявлен метод перегрузки __isset(), если он объявлен.

Это означает, что при использовании empty() для объекта, имеющего метод __get(), он всегда будет возвращать True.

Ответ 4

Я должен был сказать, был ли объект пустым или нет, но мне также пришлось игнорировать частные и защищенные свойства, поэтому я сделал эту небольшую функцию, с которой вы можете это сделать.

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

Ответ 5

Я не уверен, что это более или менее эффективно, чем кастинг в массив, но я бы догадался больше. Вы могли бы просто начать цикл объекта, и как только вы найдете что-то, у вас есть ответ и остановка цикла.

function is_obj_empty($obj){
   if( is_null($obj) ){
      return true;
   }
   foreach( $obj as $key => $val ){
      return false;
   }
   return true;
}