From da9100320e96209ff9f565b5e015db8d4931d470 Mon Sep 17 00:00:00 2001 From: BoShurik Date: Fri, 30 Oct 2020 17:59:29 +0300 Subject: [PATCH] Exclude non-initialized properties accessed with getters --- .../Normalizer/ObjectNormalizer.php | 16 ++++++++-- .../Tests/Fixtures/Php74DummyPrivate.php | 32 +++++++++++++++++++ .../Tests/Normalizer/ObjectNormalizerTest.php | 13 ++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/Php74DummyPrivate.php diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index a71313f1cc..0e1a378fe6 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -106,9 +106,19 @@ class ObjectNormalizer extends AbstractObjectNormalizer $checkPropertyInitialization = \PHP_VERSION_ID >= 70400; // properties - foreach ($reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflProperty) { - if ($checkPropertyInitialization && !$reflProperty->isInitialized($object)) { - continue; + foreach ($reflClass->getProperties() as $reflProperty) { + if ($checkPropertyInitialization) { + $isPublic = $reflProperty->isPublic(); + if (!$isPublic) { + $reflProperty->setAccessible(true); + } + if (!$reflProperty->isInitialized($object)) { + unset($attributes[$reflProperty->name]); + continue; + } + if (!$isPublic) { + continue; + } } if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Php74DummyPrivate.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Php74DummyPrivate.php new file mode 100644 index 0000000000..06061fa33c --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Php74DummyPrivate.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +/** + * @author Alexander Borisov + */ +final class Php74DummyPrivate +{ + private string $uninitializedProperty; + + private string $initializedProperty = 'defaultValue'; + + public function getUninitializedProperty(): string + { + return $this->uninitializedProperty; + } + + public function getInitializedProperty(): string + { + return $this->initializedProperty; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 4a2ac344ec..5c71063aff 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -34,6 +34,7 @@ use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy; use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy; use Symfony\Component\Serializer\Tests\Fixtures\OtherSerializedNameDummy; use Symfony\Component\Serializer\Tests\Fixtures\Php74Dummy; +use Symfony\Component\Serializer\Tests\Fixtures\Php74DummyPrivate; use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder; use Symfony\Component\Serializer\Tests\Normalizer\Features\AttributesTestTrait; use Symfony\Component\Serializer\Tests\Normalizer\Features\CallbacksObject; @@ -127,6 +128,18 @@ class ObjectNormalizerTest extends TestCase ); } + /** + * @requires PHP 7.4 + */ + public function testNormalizeObjectWithUninitializedPrivateProperties() + { + $obj = new Php74DummyPrivate(); + $this->assertEquals( + ['initializedProperty' => 'defaultValue'], + $this->normalizer->normalize($obj, 'any') + ); + } + public function testDenormalize() { $obj = $this->normalizer->denormalize(