bug #44908 [Serializer] Fix AbstractObjectNormalizer TypeError on denormalization (JustDylan23)

This PR was squashed before being merged into the 6.0 branch.

Discussion
----------

[Serializer] Fix AbstractObjectNormalizer TypeError on denormalization

| Q             | A
| ------------- | ---
| Branch?       | 6.0
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #44872
| License       | MIT
| Doc PR        |

When using dependency injection to get the serializer (instead of manually instantiating it) the object normalizer that is injected into that serializer throws a value exception when doing denormalizing the following:

```php
class ObjectOuter {
  public ObjectInner $inner;
}

class ObjectInner {
  public $foo;
}

public function testDenormalizeRecursiveWithObjectAttributeWithStringValue()
{
    $extractor = new ReflectionExtractor();
    $normalizer = new ObjectNormalizer(null, null, null, $extractor);
    $serializer = new Serializer([$normalizer]);

    $obj = $serializer->denormalize(['inner' => 'foo'], ObjectOuter::class);
    $this->assertInstanceOf(ObjectInner::class, $obj->getInner());
    }
```

This throws
```php
TypeError:
Symfony\Component\Serializer\Normalizer\AbstractNormalizer::prepareForDenormalization(): Argument #1 ($data) must be of type object|array|null, string given, called in /var/www/symfony/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php on line 368

  at vendor/symfony/serializer/Normalizer/AbstractNormalizer.php:299
  at Symfony\Component\Serializer\Normalizer\AbstractNormalizer->prepareForDenormalization('test string')
     (vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:368)
  at Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalize('test string', 'App\\Entity\\User', null, array('cache_key' => 'c93a6d4efa206ea58a62cc6b7fab8dfb', 'deserialization_path' => 'author'))
     (vendor/symfony/serializer/Serializer.php:238)
  at Symfony\Component\Serializer\Serializer->denormalize('test string', 'App\\Entity\\User', null, array('cache_key' => 'c93a6d4efa206ea58a62cc6b7fab8dfb', 'deserialization_path' => 'author'))
     (vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:559)
  at Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->validateAndDenormalize(array(object(Type)), 'App\\Entity\\Blog', 'author', 'test string', null, array('cache_key' => '44db5a926a1544b1a8585af40107ca3a', 'deserialization_path' => 'author'))
     (vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:401)
  at Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalize(array('author' => 'test string'), 'App\\Entity\\Blog', null, array('cache_key' => '44db5a926a1544b1a8585af40107ca3a'))
     (vendor/symfony/serializer/Serializer.php:238)
  at Symfony\Component\Serializer\Serializer->denormalize(array('author' => 'test string'), 'App\\Entity\\Blog')
     (src/Controller/BugReproductionController.php:18)
  at App\Controller\BugReproductionController->test(object(Serializer))
     (vendor/symfony/http-kernel/HttpKernel.php:152)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:74)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:202)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:35)
  at Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run()
     (vendor/autoload_runtime.php:29)
  at require_once('/var/www/symfony/vendor/autoload_runtime.php')
     (public/index.php:5)
```

Refer to: https://github.com/symfony/symfony/pull/44881 for the description.
Was in the middle of changing the base branch and accidentally pushed when the branch was deleted.

`@fancyweb` I implemented the requested changes

Commits
-------

89092ea279 [Serializer] Fix AbstractObjectNormalizer TypeError on denormalization
This commit is contained in:
Thomas Calvet 2022-01-12 13:47:11 +01:00
commit 3b7df9ad65
2 changed files with 13 additions and 1 deletions

View File

@ -296,7 +296,7 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn
* Normalizes the given data to an array. It's particularly useful during
* the denormalization process.
*/
protected function prepareForDenormalization(object|array|null $data): array
protected function prepareForDenormalization(mixed $data): array
{
return (array) $data;
}

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Serializer\Tests\Normalizer;
use Doctrine\Common\Annotations\AnnotationReader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
@ -387,6 +388,17 @@ class AbstractObjectNormalizerTest extends TestCase
$normalizedData = $normalizer->normalize(new EmptyDummy(), 'any', ['preserve_empty_objects' => true]);
$this->assertEquals(new \ArrayObject(), $normalizedData);
}
public function testDenormalizeRecursiveWithObjectAttributeWithStringValue()
{
$extractor = new ReflectionExtractor();
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
$serializer = new Serializer([$normalizer]);
$obj = $serializer->denormalize(['inner' => 'foo'], ObjectOuter::class);
$this->assertInstanceOf(ObjectInner::class, $obj->getInner());
}
}
class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer