-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
Symfony version(s) affected
6.4.x
Description
have a xml representation like this:
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="IB" listVersionID="88">0721-880X</cbc:ItemClassificationCode>
</cac:CommodityClassification>
ItemClassificationCode is represented by this class
class CodeType
{
public function __construct(
#[SerializedName('#')]
public string $value,
#[SerializedName('@listID')]
public ?string $listID = null,
#[SerializedName('@listAgencyID')]
public ?string $listAgencyID = null,
#[SerializedName('@listAgencyName')]
public ?string $listAgencyName = null,
#[SerializedName('@listName')]
public ?string $listName = null,
#[SerializedName('@listVersionID')]
public ?string $listVersionID = null,
#[SerializedName('@name')]
public ?string $name = null,
#[SerializedName('@languageID')]
public ?string $languageID = null,
#[SerializedName('@listURI')]
public ?string $listURI = null,
#[SerializedName('@listSchemeURI')]
public ?string $listSchemeURI = null
)
{}
}
See that the type of listVersionID
should be a string?
Now XmlEncoder assumes on decoding that the attribute could be an int:
symfony/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php
Lines 273 to 277 in 6864dbe
if (false !== $val = filter_var($attr->nodeValue, \FILTER_VALIDATE_INT)) { | |
$data['@'.$attr->nodeName] = $val; | |
continue; | |
} |
which then causes a crash in AbstractObjectNormalizer:
Symfony\Component\Serializer\Exception\NotNormalizableValueException: The type of the "listVersionID" attribute for class "UBL\UnqualifiedDataTypes\CodeType" must be one of "string" ("int" given).
There is a special case for reading string and turning it into float and other values.
But there is no case where it should be string instead
symfony/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
Lines 466 to 510 in 6864dbe
if (\is_string($data) && (XmlEncoder::FORMAT === $format || CsvEncoder::FORMAT === $format)) { | |
if ('' === $data) { | |
if (LegacyType::BUILTIN_TYPE_ARRAY === $builtinType) { | |
return []; | |
} | |
if (LegacyType::BUILTIN_TYPE_STRING === $builtinType) { | |
return ''; | |
} | |
// Don't return null yet because Object-types that come first may accept empty-string too | |
$isNullable = $isNullable ?: $type->isNullable(); | |
} | |
switch ($builtinType) { | |
case LegacyType::BUILTIN_TYPE_BOOL: | |
// according to https://www.w3.org/TR/xmlschema-2/#boolean, valid representations are "false", "true", "0" and "1" | |
if ('false' === $data || '0' === $data) { | |
$data = false; | |
} elseif ('true' === $data || '1' === $data) { | |
$data = true; | |
} else { | |
throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the "%s" attribute for class "%s" must be bool ("%s" given).', $attribute, $currentClass, $data), $data, [LegacyType::BUILTIN_TYPE_BOOL], $context['deserialization_path'] ?? null); | |
} | |
break; | |
case LegacyType::BUILTIN_TYPE_INT: | |
if (ctype_digit(isset($data[0]) && '-' === $data[0] ? substr($data, 1) : $data)) { | |
$data = (int) $data; | |
} else { | |
throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the "%s" attribute for class "%s" must be int ("%s" given).', $attribute, $currentClass, $data), $data, [LegacyType::BUILTIN_TYPE_INT], $context['deserialization_path'] ?? null); | |
} | |
break; | |
case LegacyType::BUILTIN_TYPE_FLOAT: | |
if (is_numeric($data)) { | |
return (float) $data; | |
} | |
return match ($data) { | |
'NaN' => \NAN, | |
'INF' => \INF, | |
'-INF' => -\INF, | |
default => throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the "%s" attribute for class "%s" must be float ("%s" given).', $attribute, $currentClass, $data), $data, [LegacyType::BUILTIN_TYPE_FLOAT], $context['deserialization_path'] ?? null), | |
}; | |
} | |
} |
How to reproduce
use this example xml:
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="IB" listVersionID="88">0721-880X</cbc:ItemClassificationCode>
</cac:CommodityClassification>
Possible Solution
No response
Additional Context
No response