bug #38900 [Serializer] Exclude non-initialized properties accessed with getters (BoShurik)

This PR was merged into the 4.4 branch.

Discussion
----------

[Serializer] Exclude non-initialized properties accessed with getters

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | no <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!-- required for new features -->

Allow to serialize
```php
final class Php74DummyPrivate
{
    private string $uninitializedProperty;

    private string $initializedProperty = 'defaultValue';

    public function getUninitializedProperty(): string
    {
        return $this->uninitializedProperty;
    }

    public function getInitializedProperty(): string
    {
        return $this->initializedProperty;
    }
}
```

Similar to #34791

Commits
-------

da9100320e Exclude non-initialized properties accessed with getters
This commit is contained in:
Nicolas Grekas 2021-01-26 21:44:18 +01:00
commit 484a95d8d1
3 changed files with 58 additions and 3 deletions

View File

@ -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)) {

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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 <boshurik@gmail.com>
*/
final class Php74DummyPrivate
{
private string $uninitializedProperty;
private string $initializedProperty = 'defaultValue';
public function getUninitializedProperty(): string
{
return $this->uninitializedProperty;
}
public function getInitializedProperty(): string
{
return $this->initializedProperty;
}
}

View File

@ -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(