26

I'm reading JSON data with PHP and that data contains empty objects (like {}). So the problem is, I have to handle the case when object is empty in different manner but I can't find good enough way to do the check. empty(get_object_vars(object)) looks too scary and very inefficient. Is there good way to do the check?

YakovL
  • 7,557
  • 12
  • 62
  • 102
vava
  • 24,851
  • 11
  • 64
  • 79

5 Answers5

35

How many objects are you unserializing? Unless empty(get_object_vars($object)) or casting to array proves to be a major slowdown/bottleneck, I wouldn't worry about it – Greg's solution is just fine.

I'd suggest using the the $associative flag when decoding the JSON data, though:

json_decode($data, true)

This decodes JSON objects as plain old PHP arrays instead of as stdClass objects. Then you can check for empty objects using empty() and create objects of a user-defined class instead of using stdClass, which is probably a good idea in the long run.

  • 1
    But if you find a plain old PHP array, how do you know if it was encoded from [] or {}? They aren't different in PHP, but they are in JSON. – David Spector Jun 23 '20 at 21:15
28

You could cast it to an array (unfortunately you can't do this within a call to empty():

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

Or cast to an array and count():

if (count((array)$obj))
    ...
Greg
  • 316,276
  • 54
  • 369
  • 333
  • Isn't it the same as with get_object_vars? I.e. not really efficient? :) – vava Sep 07 '09 at 13:46
  • 2
    I haven't tested it but unless you're having performance problems and have identified this as the bottleneck I don't think it's worth worrying yourself over it. – Greg Sep 07 '09 at 14:43
  • 1
    It's not easy to stop worrying about unnecessary array transformations if you were a C++ programmer most of your life :) It means memory allocation and copying stuff for something that should take just a quick check if a bit is set. – vava Sep 07 '09 at 14:57
  • The count of an array is useless to distinguish [] from {} in JSON. – David Spector Jun 23 '20 at 21:16
4

Try without using empty() which is:

get_object_vars($obj) ? TRUE : FALSE;

On PHP docs we can read the note:

When using empty() on inaccessible object properties, the __isset() overloading method will be called, if declared.

Which means when using empty() on an object which is having __get() method, it will always return True.

kenorb
  • 155,785
  • 88
  • 678
  • 743
0

I am not sure if this is more or less effective than casting to an array but I would guess more. You could just start to loop the object and as soon as you find something you have an answer and stop looping.

function is_obj_empty($obj){
   if( is_null($obj) ){
      return true;
   }
   foreach( $obj as $key => $val ){
      return false;
   }
   return true;
}
Adam
  • 6,539
  • 3
  • 39
  • 65
0

I had to tell if an object was empty or not, but I also had to ignore private and protected properties, so I made this little function with which you can do this.

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;
}
Parziphal
  • 6,222
  • 4
  • 34
  • 36