class PropertyNormalizer
Converts between objects and arrays by mapping properties.
The normalization process looks for all the object's properties (public and private). The result is a map from property names to property values. Property values are normalized through the serializer.
The denormalization first looks at the constructor of the given class to see if any of the parameters have the same name as one of the properties. The constructor is then called with all parameters or an exception is thrown if any required parameters were not present as properties. Then the denormalizer walks through the given map of property names to property values to see if a property with the corresponding name exists. If found, the property gets the value.
@author Matthieu Napoli <matthieu@mnapoli.fr> @author Kévin Dunglas <dunglas@gmail.com>
Hierarchy
- class \Symfony\Component\Serializer\Normalizer\AbstractNormalizer implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface, \Symfony\Component\Serializer\Normalizer\DenormalizerInterface, \Symfony\Component\Serializer\SerializerAwareInterface uses \Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait, \Symfony\Component\Serializer\SerializerAwareTrait
- class \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer extends \Symfony\Component\Serializer\Normalizer\AbstractNormalizer
- class \Symfony\Component\Serializer\Normalizer\PropertyNormalizer extends \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer
- class \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer extends \Symfony\Component\Serializer\Normalizer\AbstractNormalizer
Expanded class hierarchy of PropertyNormalizer
1 file declares its use of PropertyNormalizer
- PropertyNormalizerContextBuilder.php in vendor/
symfony/ serializer/ Context/ Normalizer/ PropertyNormalizerContextBuilder.php
File
-
vendor/
symfony/ serializer/ Normalizer/ PropertyNormalizer.php, line 37
Namespace
Symfony\Component\Serializer\NormalizerView source
final class PropertyNormalizer extends AbstractObjectNormalizer {
public const NORMALIZE_PUBLIC = 1;
public const NORMALIZE_PROTECTED = 2;
public const NORMALIZE_PRIVATE = 4;
/**
* Flag to control whether fields should be output based on visibility.
*/
public const NORMALIZE_VISIBILITY = 'normalize_visibility';
public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = []) {
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);
if (!isset($this->defaultContext[self::NORMALIZE_VISIBILITY])) {
$this->defaultContext[self::NORMALIZE_VISIBILITY] = self::NORMALIZE_PUBLIC | self::NORMALIZE_PROTECTED | self::NORMALIZE_PRIVATE;
}
}
public function getSupportedTypes(?string $format) : array {
return [
'object' => true,
];
}
public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool {
return parent::supportsNormalization($data, $format) && $this->supports($data::class);
}
public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool {
return parent::supportsDenormalization($data, $type, $format) && $this->supports($type);
}
/**
* Checks if the given class has any non-static property.
*/
private function supports(string $class) : bool {
if ($this->classDiscriminatorResolver?->getMappingForClass($class)) {
return true;
}
$class = new \ReflectionClass($class);
// We look for at least one non-static property
do {
foreach ($class->getProperties() as $property) {
if (!$property->isStatic()) {
return true;
}
}
} while ($class = $class->getParentClass());
return false;
}
protected function isAllowedAttribute(object|string $classOrObject, string $attribute, ?string $format = null, array $context = []) : bool {
if (!parent::isAllowedAttribute($classOrObject, $attribute, $format, $context)) {
return false;
}
try {
$reflectionProperty = $this->getReflectionProperty($classOrObject, $attribute);
} catch (\ReflectionException) {
return false;
}
if ($reflectionProperty->isStatic()) {
return false;
}
$normalizeVisibility = $context[self::NORMALIZE_VISIBILITY] ?? $this->defaultContext[self::NORMALIZE_VISIBILITY];
if (self::NORMALIZE_PUBLIC & $normalizeVisibility && $reflectionProperty->isPublic()) {
return true;
}
if (self::NORMALIZE_PROTECTED & $normalizeVisibility && $reflectionProperty->isProtected()) {
return true;
}
if (self::NORMALIZE_PRIVATE & $normalizeVisibility && $reflectionProperty->isPrivate()) {
return true;
}
return false;
}
protected function extractAttributes(object $object, ?string $format = null, array $context = []) : array {
$reflectionObject = new \ReflectionObject($object);
$attributes = [];
do {
foreach ($reflectionObject->getProperties() as $property) {
if (!$this->isAllowedAttribute($reflectionObject->getName(), $property->name, $format, $context)) {
continue;
}
$attributes[] = $property->name;
}
} while ($reflectionObject = $reflectionObject->getParentClass());
return array_unique($attributes);
}
protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []) : mixed {
try {
$reflectionProperty = $this->getReflectionProperty($object, $attribute);
} catch (\ReflectionException) {
return null;
}
if ($reflectionProperty->hasType()) {
return $reflectionProperty->getValue($object);
}
if (!method_exists($object, '__get') && !isset($object->{$attribute})) {
$propertyValues = (array) $object;
if ($reflectionProperty->isPublic() && !\array_key_exists($reflectionProperty->name, $propertyValues) || $reflectionProperty->isProtected() && !\array_key_exists("\x00*\x00{$reflectionProperty->name}", $propertyValues) || $reflectionProperty->isPrivate() && !\array_key_exists("\x00{$reflectionProperty->class}\x00{$reflectionProperty->name}", $propertyValues)) {
throw new UninitializedPropertyException(\sprintf('The property "%s::$%s" is not initialized.', $object::class, $reflectionProperty->name));
}
}
return $reflectionProperty->getValue($object);
}
protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = []) : void {
try {
$reflectionProperty = $this->getReflectionProperty($object, $attribute);
} catch (\ReflectionException) {
return;
}
if ($reflectionProperty->isStatic()) {
return;
}
$reflectionProperty->setValue($object, $value);
}
/**
* @throws \ReflectionException
*/
private function getReflectionProperty(string|object $classOrObject, string $attribute) : \ReflectionProperty {
$reflectionClass = new \ReflectionClass($classOrObject);
while (true) {
try {
return $reflectionClass->getProperty($attribute);
} catch (\ReflectionException $e) {
if (!($reflectionClass = $reflectionClass->getParentClass())) {
throw $e;
}
}
}
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|
AbstractNormalizer::$defaultContext | protected | property | |||
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES | public | constant | If ATTRIBUTES are specified, and the source has fields that are not part of that list, either ignore those attributes (true) or throw an ExtraAttributesException (false). |
||
AbstractNormalizer::applyCallbacks | final protected | function | |||
AbstractNormalizer::applyFilterBool | final protected | function | |||
AbstractNormalizer::ATTRIBUTES | public | constant | Limit (de)normalize to the specified names. | ||
AbstractNormalizer::CALLBACKS | public | constant | Hashmap of field name => callable to (de)normalize this field. | ||
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER | public | constant | Handler to call when a circular reference has been detected. | ||
AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT | public | constant | How many loops of circular reference to allow while normalizing. | ||
AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT_COUNTERS | protected | constant | @internal | ||
AbstractNormalizer::DEFAULT_CONSTRUCTOR_ARGUMENTS | public | constant | Hashmap of default values for constructor arguments. | ||
AbstractNormalizer::FILTER_BOOL | public | constant | Flag to control whether a non-boolean value should be filtered using the filter_var function with the {\FILTER_VALIDATE_BOOL filter before casting it to a boolean. |
||
AbstractNormalizer::getAllowedAttributes | protected | function | Gets attributes to normalize using groups. | 1 | |
AbstractNormalizer::getAttributeDenormalizationContext | protected | function | Computes the denormalization context merged with current one. Metadata always wins over global context, as more specific. | ||
AbstractNormalizer::getAttributeMetadata | protected | function | @internal | ||
AbstractNormalizer::getAttributeNormalizationContext | protected | function | Computes the normalization context merged with current one. Metadata always wins over global context, as more specific. | ||
AbstractNormalizer::getConstructor | protected | function | Returns the method to use to construct an object. This method must be either the object constructor or static. |
||
AbstractNormalizer::getGroups | protected | function | |||
AbstractNormalizer::GROUPS | public | constant | Only (de)normalize attributes that are in the specified groups. | ||
AbstractNormalizer::handleCircularReference | protected | function | Handles a circular reference. | ||
AbstractNormalizer::IGNORED_ATTRIBUTES | public | constant | Skip the specified attributes when normalizing an object tree. | ||
AbstractNormalizer::isCircularReference | protected | function | Detects if the configured circular reference limit is reached. | ||
AbstractNormalizer::OBJECT_TO_POPULATE | public | constant | Instead of creating a new instance of an object, update the specified object. | ||
AbstractNormalizer::prepareForDenormalization | protected | function | Normalizes the given data to an array. It's particularly useful during the denormalization process. |
||
AbstractNormalizer::REQUIRE_ALL_PROPERTIES | public | constant | Require all properties to be listed in the input instead of falling back to null for nullable ones. |
||
AbstractNormalizer::validateCallbackContext | final protected | function | Validate callbacks set in context. | ||
AbstractObjectNormalizer::$attributesCache | private | property | |||
AbstractObjectNormalizer::$classDiscriminatorResolver | protected | property | |||
AbstractObjectNormalizer::$objectClassResolver | private | property | 1 | ||
AbstractObjectNormalizer::$typeCache | private | property | |||
AbstractObjectNormalizer::createChildContext | protected | function | Overwritten to update the cache key for the child. | Overrides AbstractNormalizer::createChildContext | |
AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE | public | constant | Flag to tell the denormalizer to also populate existing objects on attributes of the main object. |
||
AbstractObjectNormalizer::denormalize | public | function | Denormalizes data back into an object of the given class. | Overrides DenormalizerInterface::denormalize | |
AbstractObjectNormalizer::denormalizeParameter | protected | function | @internal | Overrides AbstractNormalizer::denormalizeParameter | |
AbstractObjectNormalizer::DEPTH_KEY_PATTERN | public | constant | How to track the current depth in the context. | ||
AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT | public | constant | While denormalizing, we can verify that type matches. | ||
AbstractObjectNormalizer::ENABLE_MAX_DEPTH | public | constant | Set to true to respect the max depth metadata on fields. | ||
AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY | public | constant | Specify which context key are not relevant to determine which attributes of an object to (de)normalize. |
||
AbstractObjectNormalizer::getAttributes | protected | function | Gets and caches attributes for the given object, format and context. | ||
AbstractObjectNormalizer::getCacheKey | private | function | Builds the cache key for the attributes cache. | ||
AbstractObjectNormalizer::getMappedClass | private | function | |||
AbstractObjectNormalizer::getNestedAttributes | private | function | Returns all attributes with a SerializedPath attribute and the respective path. | ||
AbstractObjectNormalizer::getPropertyType | private | function | BC layer for PropertyTypeExtractorInterface::getTypes(). Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0). |
||
AbstractObjectNormalizer::getType | private | function | |||
AbstractObjectNormalizer::instantiateObject | protected | function | Instantiates an object using constructor parameters when needed. | Overrides AbstractNormalizer::instantiateObject | |
AbstractObjectNormalizer::isMaxDepthReached | private | function | Is the max depth reached for the given attribute? | ||
AbstractObjectNormalizer::isUninitializedValueError | private | function | This error may occur when specific object normalizer implementation gets attribute value by accessing a public uninitialized property or by calling a method accessing such property. |
||
AbstractObjectNormalizer::MAX_DEPTH_HANDLER | public | constant | Callback to allow to set a value for an attribute when the max depth has been reached. |
||
AbstractObjectNormalizer::normalize | public | function | Normalizes data into a set of arrays/scalars. | Overrides NormalizerInterface::normalize | |
AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS | public | constant | Flag to control whether an empty object should be kept as an object (in JSON: {}) or converted to a list (in JSON: []). |
||
AbstractObjectNormalizer::removeNestedValue | private | function | |||
AbstractObjectNormalizer::SKIP_NULL_VALUES | public | constant | Flag to control whether fields with the value `null` should be output when normalizing or omitted. |
||
AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES | public | constant | Flag to control whether uninitialized PHP>=7.4 typed class properties should be excluded when normalizing. |
||
AbstractObjectNormalizer::updateData | private | function | Sets an attribute and apply the name converter if necessary. | ||
AbstractObjectNormalizer::validateAndDenormalize | private | function | Validates the submitted data and denormalizes it. | ||
AbstractObjectNormalizer::validateAndDenormalizeLegacy | private | function | Validates the submitted data and denormalizes it. | ||
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS | public | constant | |||
ObjectToPopulateTrait::extractObjectToPopulate | protected | function | Extract the `object_to_populate` field from the context if it exists and is an instance of the provided $class. |
||
PropertyNormalizer::extractAttributes | protected | function | Extracts attributes to normalize from the class of the given object, format and context. | Overrides AbstractObjectNormalizer::extractAttributes | |
PropertyNormalizer::getAttributeValue | protected | function | Gets the attribute value. | Overrides AbstractObjectNormalizer::getAttributeValue | |
PropertyNormalizer::getReflectionProperty | private | function | |||
PropertyNormalizer::getSupportedTypes | public | function | Returns the types potentially supported by this normalizer. | Overrides NormalizerInterface::getSupportedTypes | |
PropertyNormalizer::isAllowedAttribute | protected | function | Is this attribute allowed? | Overrides AbstractNormalizer::isAllowedAttribute | |
PropertyNormalizer::NORMALIZE_PRIVATE | public | constant | |||
PropertyNormalizer::NORMALIZE_PROTECTED | public | constant | |||
PropertyNormalizer::NORMALIZE_PUBLIC | public | constant | |||
PropertyNormalizer::NORMALIZE_VISIBILITY | public | constant | Flag to control whether fields should be output based on visibility. | ||
PropertyNormalizer::setAttributeValue | protected | function | Overrides AbstractObjectNormalizer::setAttributeValue | ||
PropertyNormalizer::supports | private | function | Checks if the given class has any non-static property. | ||
PropertyNormalizer::supportsDenormalization | public | function | Checks whether the given class is supported for denormalization by this normalizer. | Overrides AbstractObjectNormalizer::supportsDenormalization | |
PropertyNormalizer::supportsNormalization | public | function | Checks whether the given class is supported for normalization by this normalizer. | Overrides AbstractObjectNormalizer::supportsNormalization | |
PropertyNormalizer::__construct | public | function | Sets the {@link ClassMetadataFactoryInterface} to use. | Overrides AbstractObjectNormalizer::__construct | |
SerializerAwareTrait::$serializer | protected | property | |||
SerializerAwareTrait::setSerializer | public | function |