[Serializer] Add a MaxDepth handler
This commit is contained in:
parent
136408937b
commit
ed975c764b
@ -731,6 +731,7 @@ class Configuration implements ConfigurationInterface
|
||||
->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end()
|
||||
->scalarNode('name_converter')->end()
|
||||
->scalarNode('circular_reference_handler')->end()
|
||||
->scalarNode('max_depth_handler')->end()
|
||||
->arrayNode('mapping')
|
||||
->addDefaultsIfNotSet()
|
||||
->fixXmlConfig('path')
|
||||
|
@ -1273,6 +1273,10 @@ class FrameworkExtension extends Extension
|
||||
if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) {
|
||||
$container->getDefinition('serializer.normalizer.object')->addMethodCall('setCircularReferenceHandler', array(new Reference($config['circular_reference_handler'])));
|
||||
}
|
||||
|
||||
if ($config['max_depth_handler'] ?? false) {
|
||||
$container->getDefinition('serializer.normalizer.object')->addMethodCall('setMaxDepthHandler', array(new Reference($config['max_depth_handler'])));
|
||||
}
|
||||
}
|
||||
|
||||
private function registerPropertyInfoConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
|
@ -239,6 +239,7 @@
|
||||
<xsd:attribute name="cache" type="xsd:string" />
|
||||
<xsd:attribute name="enable-annotations" type="xsd:boolean" />
|
||||
<xsd:attribute name="name-converter" type="xsd:string" />
|
||||
<xsd:attribute name="max-depth-handler" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="property_info">
|
||||
|
@ -68,6 +68,7 @@ $container->loadFromExtension('framework', array(
|
||||
'enabled' => true,
|
||||
'enable_annotations' => true,
|
||||
'name_converter' => 'serializer.name_converter.camel_case_to_snake_case',
|
||||
'max_depth_handler' => 'my.max.depth.handler',
|
||||
),
|
||||
'property_info' => true,
|
||||
'ide' => 'file%%link%%format',
|
||||
|
@ -41,7 +41,7 @@
|
||||
</framework:translator>
|
||||
<framework:validation enabled="true" />
|
||||
<framework:annotations cache="file" debug="true" file-cache-dir="%kernel.cache_dir%/annotations" />
|
||||
<framework:serializer enabled="true" enable-annotations="true" name-converter="serializer.name_converter.camel_case_to_snake_case" />
|
||||
<framework:serializer enabled="true" enable-annotations="true" name-converter="serializer.name_converter.camel_case_to_snake_case" max-depth-handler="my.max.depth.handler" />
|
||||
<framework:property-info />
|
||||
</framework:config>
|
||||
</container>
|
||||
|
@ -54,6 +54,7 @@ framework:
|
||||
enabled: true
|
||||
enable_annotations: true
|
||||
name_converter: serializer.name_converter.camel_case_to_snake_case
|
||||
max_depth_handler: my.max.depth.handler
|
||||
property_info: ~
|
||||
ide: file%%link%%format
|
||||
request:
|
||||
|
@ -804,6 +804,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertNull($container->getDefinition('serializer.mapping.class_metadata_factory')->getArgument(1));
|
||||
$this->assertEquals(new Reference('serializer.name_converter.camel_case_to_snake_case'), $container->getDefinition('serializer.normalizer.object')->getArgument(1));
|
||||
$this->assertEquals(new Reference('property_info', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $container->getDefinition('serializer.normalizer.object')->getArgument(3));
|
||||
$this->assertEquals(array('setMaxDepthHandler', array(new Reference('my.max.depth.handler'))), $container->getDefinition('serializer.normalizer.object')->getMethodCalls()[0]);
|
||||
}
|
||||
|
||||
public function testRegisterSerializerExtractor()
|
||||
|
@ -9,6 +9,8 @@ CHANGELOG
|
||||
* added an optional `default_constructor_arguments` option of context to specify a default data in
|
||||
case the object is not initializable by its constructor because of data missing
|
||||
* added optional `bool $escapeFormulas = false` argument to `CsvEncoder::__construct`
|
||||
* added `AbstractObjectNormalizer::setMaxDepthHandler` to set a handler to call when the configured
|
||||
maximum depth is reached
|
||||
|
||||
4.0.0
|
||||
-----
|
||||
|
@ -41,6 +41,11 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
private $attributesCache = array();
|
||||
private $cache = array();
|
||||
|
||||
/**
|
||||
* @var callable|null
|
||||
*/
|
||||
private $maxDepthHandler;
|
||||
|
||||
/**
|
||||
* @var ClassDiscriminatorResolverInterface|null
|
||||
*/
|
||||
@ -86,11 +91,15 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
$attributesMetadata = $this->classMetadataFactory ? $this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() : null;
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
if (null !== $attributesMetadata && $this->isMaxDepthReached($attributesMetadata, $class, $attribute, $context)) {
|
||||
$maxDepthReached = false;
|
||||
if (null !== $attributesMetadata && ($maxDepthReached = $this->isMaxDepthReached($attributesMetadata, $class, $attribute, $context)) && !$this->maxDepthHandler) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributeValue = $this->getAttributeValue($object, $attribute, $format, $context);
|
||||
if ($maxDepthReached) {
|
||||
$attributeValue = \call_user_func($this->maxDepthHandler, $attributeValue);
|
||||
}
|
||||
|
||||
if (isset($this->callbacks[$attribute])) {
|
||||
$attributeValue = call_user_func($this->callbacks[$attribute], $attributeValue);
|
||||
@ -204,6 +213,14 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
*/
|
||||
abstract protected function getAttributeValue($object, $attribute, $format = null, array $context = array());
|
||||
|
||||
/**
|
||||
* Sets an handler function that will be called when the max depth is reached.
|
||||
*/
|
||||
public function setMaxDepthHandler(?callable $handler): void
|
||||
{
|
||||
$this->maxDepthHandler = $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -613,6 +613,27 @@ class ObjectNormalizerTest extends TestCase
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'bar' => null,
|
||||
'foo' => 'level1',
|
||||
'child' => array(
|
||||
'bar' => null,
|
||||
'foo' => 'level2',
|
||||
'child' => array(
|
||||
'bar' => null,
|
||||
'child' => null,
|
||||
'foo' => 'handler',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$this->normalizer->setMaxDepthHandler(function ($obj) {
|
||||
return 'handler';
|
||||
});
|
||||
|
||||
$result = $serializer->normalize($level1, null, array(ObjectNormalizer::ENABLE_MAX_DEPTH => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user