kphp icon indicating copy to clipboard operation
kphp copied to clipboard

to_array_debug(): suppressed visitting private and protected members.…

Open comm644 opened this issue 1 year ago • 5 comments

For to_array_debug(): suppressed visitting private and protected members. Because this method converts class instance to mixed for json_encode() , but json_encode must not convert private and protected fields.

test case:

<?php
class A
{
        public array $b = [];
        private int $privateVal = 1;
        protected  int $protectedVal = 2;
}
$obj = new A;

//echo json_encode($obj ); //does not accept class instance

$mixed= to_array_debug($obj, false);
print_r(  $mixed ); //for manual check

if  (count($mixed) !== 1 ) throw new \RuntimeException("to_array_debug() generated private and protected fields");
echo "ok\n";

comm644 avatar Mar 11 '23 21:03 comm644

to_array_debug and json_encode have no connection between ones. As the name says, to_array_debug is for debug purposes only.

Check JsonEncoder and visibility_policy.

vkaverin avatar Mar 11 '23 22:03 vkaverin

It's about JsonEncoder. JsonEncoder - It's good but next step for serialize/unserialize objects. Simple way (and migration simple) is next:

echo json_encode( to_array_debug( $obj )) ;

for real simple debug already introduced print_r().

On the other hand: it too difficult mark ALL CLASSES with this attribute when I would like to get same behavior as json_encode().

comm644 avatar Mar 11 '23 23:03 comm644

The only correct way is still JsonEncoder. It has a lot of customizations. You can make your own class that extends JsonEncoder and override visibility_policy, so you don't need to mark classes with any annotations.

vkaverin avatar Mar 11 '23 23:03 vkaverin

Yes but in polyfill....

class JsonEncoder {
  // these constants can be overridden in child classes
  const rename_policy     = 'none';
  const visibility_policy = 'all';
  const skip_if_default   = false;
  const float_precision   = 0;

  private function __construct() { }
..
  1. Constructor of JsonEncoder is private. We can't implement derived class.
  2. Method ::encode() declared as static and can't use properties of my instance of JsonEncoder

Need to update documentation how to implement json_encode_object($instance) with same behaviour as json_encode(). (only public methods for all classes aka global policy)

comm644 avatar Mar 12 '23 10:03 comm644

  1. Private constructor doesn't stop you from extending JsonEncoder, since you don't need to instantiate it.
  2. You don't need to use overridden constants manually, all you need is just to override them and use YourJsonEncoder::encode.

vkaverin avatar Mar 12 '23 15:03 vkaverin