You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When deserializing XML into an object, sometimes the serializer "guesses" a field containing only digits to be an integer.
This behaviour can be controlled via the TYPE_CAST_ATTRIBUTES/xml_type_cast_attributes option.
But, this only applies if the node in question has child nodes. If its just a lone XML element without child nodes, some kind of "quick path" is taken that just copies the attribute values to an arry (as strings):
<?phpdeclare(strict_types=1);
useSymfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
useSymfony\Component\PropertyInfo\PropertyInfoExtractor;
useSymfony\Component\Serializer\Annotation\SerializedName;
useSymfony\Component\Serializer\Encoder\XmlEncoder;
useSymfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
useSymfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
useSymfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
useSymfony\Component\Serializer\Mapping\Loader\LoaderChain;
useSymfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
useSymfony\Component\Serializer\Normalizer\PropertyNormalizer;
useSymfony\Component\Serializer\Serializer;
require_once'vendor/autoload.php';
class TestClass
{
publicfunction__construct(
#[SerializedName('@aString')]
publicreadonlystring$aString,
#[SerializedName('@anInt')]
publicreadonlyint$anInt
) {
}
}
$metadataFactory = newClassMetadataFactory(newLoaderChain([newAnnotationLoader(null)]));
$nameConverter = newMetadataAwareNameConverter($metadataFactory);
$propertyTypeExtractor = newPropertyInfoExtractor([], [newReflectionExtractor()]);
$classDiscriminator = newClassDiscriminatorFromClassMetadata($metadataFactory);
$serializer = newSerializer(
[
newPropertyNormalizer($metadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminator)
],
[
newXmlEncoder()
]
);
// this worksvar_dump($serializer->deserialize('<outer aString="12345" anInt="12345"></outer>', TestClass::class, 'xml'));
// this also worksvar_dump($serializer->deserialize('<outer aString="12345" anInt="12345"> </outer>', TestClass::class, 'xml', ['xml_type_cast_attributes' => false]));
// NotNormalizableValueException: The type of the "aString" attribute for class "TestClass" must be one of "string" ("int" given). var_dump($serializer->deserialize('<outer aString="12345" anInt="12345"> </outer>', TestClass::class, 'xml'));
Possible Solution
Handling attribute type "guessing" identical, independent from $rootNode->hasChildNodes() should result in a more consistent result. But I may be missing part of the picture here.
Additional Context
No response
The text was updated successfully, but these errors were encountered:
Symfony version(s) affected
6.3.4
Description
When deserializing XML into an object, sometimes the serializer "guesses" a field containing only digits to be an integer.
This behaviour can be controlled via the
TYPE_CAST_ATTRIBUTES
/xml_type_cast_attributes
option.But, this only applies if the node in question has child nodes. If its just a lone XML element without child nodes, some kind of "quick path" is taken that just copies the attribute values to an arry (as strings):
This causes different encoding results for very similar XML strings (see reproducer).
For me, setting
xml_type_cast_attributes
tofalse
works around the issue, as that produces the (for us) correct behaviour in allcases.
How to reproduce
Installed the followin libraries via composer:
Possible Solution
Handling attribute type "guessing" identical, independent from
$rootNode->hasChildNodes()
should result in a more consistent result. But I may be missing part of the picture here.Additional Context
No response
The text was updated successfully, but these errors were encountered: