[Serializer] Add the possibility to filter attributes
This commit is contained in:
parent
7c5dcfcdb8
commit
b3826fb0e7
@ -236,7 +236,20 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
*/
|
||||
protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = array())
|
||||
{
|
||||
return !in_array($attribute, $this->ignoredAttributes);
|
||||
if (in_array($attribute, $this->ignoredAttributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($context['attributes'][$attribute])) {
|
||||
// Nested attributes
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isset($context['attributes']) && is_array($context['attributes'])) {
|
||||
return in_array($attribute, $context['attributes'], true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,7 +337,7 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
$key = $this->nameConverter ? $this->nameConverter->normalize($paramName) : $paramName;
|
||||
|
||||
$allowed = $allowedAttributes === false || in_array($paramName, $allowedAttributes);
|
||||
$ignored = in_array($paramName, $this->ignoredAttributes);
|
||||
$ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context);
|
||||
if (method_exists($constructorParameter, 'isVariadic') && $constructorParameter->isVariadic()) {
|
||||
if ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) {
|
||||
if (!is_array($data[$paramName])) {
|
||||
@ -341,7 +354,7 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
throw new LogicException(sprintf('Cannot create an instance of %s from serialized data because the serializer inject in "%s" is not a denormalizer', $constructorParameter->getClass(), static::class));
|
||||
}
|
||||
$parameterClass = $constructorParameter->getClass()->getName();
|
||||
$parameterData = $this->serializer->denormalize($parameterData, $parameterClass, $format, $context);
|
||||
$parameterData = $this->serializer->denormalize($parameterData, $parameterClass, $format, $this->createChildContext($context, $paramName));
|
||||
}
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new RuntimeException(sprintf('Could not determine the class of the parameter "%s".', $key), 0, $e);
|
||||
@ -372,4 +385,21 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
|
||||
return new $class();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $parentContext
|
||||
* @param string $attribute
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function createChildContext(array $parentContext, $attribute)
|
||||
{
|
||||
if (isset($parentContext['attributes'][$attribute])) {
|
||||
$parentContext['attributes'] = $parentContext['attributes'][$attribute];
|
||||
}
|
||||
|
||||
return $parentContext;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer', $attribute));
|
||||
}
|
||||
|
||||
$data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $context));
|
||||
$data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $this->createChildContext($context, $attribute)));
|
||||
}
|
||||
|
||||
return $data;
|
||||
@ -268,7 +268,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
}
|
||||
|
||||
if ($this->serializer->supportsDenormalization($data, $class, $format)) {
|
||||
return $this->serializer->denormalize($data, $class, $format, $context);
|
||||
return $this->serializer->denormalize($data, $class, $format, $this->createChildContext($context, $attribute));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -643,6 +643,70 @@ class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertSame(array('foo' => 'bar', 'bar' => 'foo'), $normalizer->normalize($data, null, array('include_foo_and_bar' => true)));
|
||||
}
|
||||
|
||||
public function testAttributesContextNormalize()
|
||||
{
|
||||
$normalizer = new ObjectNormalizer();
|
||||
$serializer = new Serializer(array($normalizer));
|
||||
|
||||
$objectInner = new ObjectInner();
|
||||
$objectInner->foo = 'innerFoo';
|
||||
$objectInner->bar = 'innerBar';
|
||||
|
||||
$objectDummy = new ObjectDummy();
|
||||
$objectDummy->setFoo('foo');
|
||||
$objectDummy->setBaz(true);
|
||||
$objectDummy->setObject($objectInner);
|
||||
|
||||
$context = array('attributes' => array('foo', 'baz', 'object' => array('foo')));
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'foo' => 'foo',
|
||||
'baz' => true,
|
||||
'object' => array('foo' => 'innerFoo'),
|
||||
),
|
||||
$serializer->normalize($objectDummy, null, $context)
|
||||
);
|
||||
}
|
||||
|
||||
public function testAttributesContextDenormalize()
|
||||
{
|
||||
$normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
|
||||
$serializer = new Serializer(array($normalizer));
|
||||
|
||||
$objectInner = new ObjectInner();
|
||||
$objectInner->foo = 'innerFoo';
|
||||
|
||||
$objectOuter = new ObjectOuter();
|
||||
$objectOuter->bar = 'bar';
|
||||
$objectOuter->setInner($objectInner);
|
||||
|
||||
$context = array('attributes' => array('bar', 'inner' => array('foo')));
|
||||
$this->assertEquals($objectOuter, $serializer->denormalize(
|
||||
array(
|
||||
'foo' => 'foo',
|
||||
'bar' => 'bar',
|
||||
'date' => '2017-02-03',
|
||||
'inner' => array('foo' => 'innerFoo', 'bar' => 'innerBar'),
|
||||
), ObjectOuter::class, null, $context));
|
||||
}
|
||||
|
||||
public function testAttributesContextDenormalizeConstructor()
|
||||
{
|
||||
$normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
|
||||
$serializer = new Serializer(array($normalizer));
|
||||
|
||||
$objectInner = new ObjectInner();
|
||||
$objectInner->bar = 'bar';
|
||||
|
||||
$obj = new DummyWithConstructorObjectAndDefaultValue('a', $objectInner);
|
||||
|
||||
$context = array('attributes' => array('inner' => array('bar')));
|
||||
$this->assertEquals($obj, $serializer->denormalize(array(
|
||||
'foo' => 'b',
|
||||
'inner' => array('foo' => 'foo', 'bar' => 'bar'),
|
||||
), DummyWithConstructorObjectAndDefaultValue::class, null, $context));
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectDummy
|
||||
@ -813,6 +877,8 @@ class ObjectTypeHinted
|
||||
|
||||
class ObjectOuter
|
||||
{
|
||||
public $foo;
|
||||
public $bar;
|
||||
private $inner;
|
||||
private $date;
|
||||
|
||||
@ -910,3 +976,25 @@ class JsonNumber
|
||||
*/
|
||||
public $number;
|
||||
}
|
||||
|
||||
class DummyWithConstructorObjectAndDefaultValue
|
||||
{
|
||||
private $foo;
|
||||
private $inner;
|
||||
|
||||
public function __construct($foo = 'a', ObjectInner $inner)
|
||||
{
|
||||
$this->foo = $foo;
|
||||
$this->inner = $inner;
|
||||
}
|
||||
|
||||
public function getFoo()
|
||||
{
|
||||
return $this->foo;
|
||||
}
|
||||
|
||||
public function getInner()
|
||||
{
|
||||
return $this->inner;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user