[Serializer] Use object class resolver when extracting attributes

This commit is contained in:
Joel Wurtz 2019-03-26 15:05:43 +01:00 committed by Fabien Potencier
parent 8d7e002168
commit 1d8b5af3f0
2 changed files with 39 additions and 1 deletions

View File

@ -32,6 +32,8 @@ class ObjectNormalizer extends AbstractObjectNormalizer
private $discriminatorCache = []; private $discriminatorCache = [];
private $objectClassResolver;
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = [])
{ {
if (!\class_exists(PropertyAccess::class)) { if (!\class_exists(PropertyAccess::class)) {
@ -41,6 +43,7 @@ class ObjectNormalizer extends AbstractObjectNormalizer
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext); parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
$this->objectClassResolver = $objectClassResolver;
} }
/** /**
@ -60,7 +63,9 @@ class ObjectNormalizer extends AbstractObjectNormalizer
$attributes = []; $attributes = [];
// methods // methods
$reflClass = new \ReflectionClass($object); $class = $this->objectClassResolver ? ($this->objectClassResolver)($object) : \get_class($object);
$reflClass = new \ReflectionClass($class);
foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) { foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
if ( if (
0 !== $reflMethod->getNumberOfRequiredParameters() || 0 !== $reflMethod->getNumberOfRequiredParameters() ||

View File

@ -1003,6 +1003,34 @@ class ObjectNormalizerTest extends TestCase
$normalizer = new ObjectNormalizer(null, $nameConverter); $normalizer = new ObjectNormalizer(null, $nameConverter);
$this->assertArrayHasKey('foo-Symfony\Component\Serializer\Tests\Normalizer\ObjectDummy-json-bar', $normalizer->normalize(new ObjectDummy(), 'json', ['foo' => 'bar'])); $this->assertArrayHasKey('foo-Symfony\Component\Serializer\Tests\Normalizer\ObjectDummy-json-bar', $normalizer->normalize(new ObjectDummy(), 'json', ['foo' => 'bar']));
} }
public function testObjectClassResolver()
{
$classResolver = function ($object) {
return ObjectDummy::class;
};
$normalizer = new ObjectNormalizer(null, null, null, null, null, $classResolver);
$obj = new ProxyObjectDummy();
$obj->setFoo('foo');
$obj->bar = 'bar';
$obj->setBaz(true);
$obj->setCamelCase('camelcase');
$obj->unwantedProperty = 'notwanted';
$this->assertEquals(
[
'foo' => 'foo',
'bar' => 'bar',
'baz' => true,
'fooBar' => 'foobar',
'camelCase' => 'camelcase',
'object' => null,
],
$normalizer->normalize($obj, 'any')
);
}
} }
class ObjectDummy class ObjectDummy
@ -1064,6 +1092,11 @@ class ObjectDummy
} }
} }
class ProxyObjectDummy extends ObjectDummy
{
public $unwantedProperty;
}
class ObjectConstructorDummy class ObjectConstructorDummy
{ {
protected $foo; protected $foo;