Description
Symfony version(s) affected: 3.4
Description
If an XML attribute contains a positive float value which starts with 0
, e.g. 0.123
, XmlEncoder will decode it as a string.
If a float value starts with some other number, or is negative, then it is decoded as a float.
How to reproduce
<?php
require_once __DIR__.'/vendor/autoload.php';
use Symfony\Component\Serializer\Encoder\XmlEncoder;
$encoder = new XmlEncoder();
$xml = '<document value="0.123">...</document>';
$result = $encoder->decode($xml, 'xml');
var_dump($result);
// array(2) {
// ["@value"]=>
// string(5) "0.123" <-- a float was expected, but it's a string
// ["#"]=>
// string(3) "..."
// }
Note that:
$xml = '<document value="1.123">...</document>';
$result = $encoder->decode($xml, 'xml');
var_dump($result);
// array(2) {
// ["@value"]=>
// float(1.123) <-- float, as expected
// ["#"]=>
// string(3) "..."
// }
$xml = '<document value="-1.123">...</document>';
$result = $encoder->decode($xml, 'xml');
var_dump($result);
// array(2) {
// ["@value"]=>
// float(-1.123) <-- negative values are also fine
// ["#"]=>
// string(3) "..."
// }
$xml = '<document value="-0.123">...</document>';
$result = $encoder->decode($xml, 'xml');
var_dump($result);
// array(2) {
// ["@value"]=>
// float(-0.123) <-- ...even if negative value starts with 0
// ["#"]=>
// string(3) "..."
// }
Possible Solution
It looks like this behaviour was introduced in #32438 (as suggested here).
The naive approach would be to just extend the added check with the "but zero is not followed by a dot" condition, like in #38669.
Seems to work, but it feels like a nasty workaround, not a proper solution. And probably someone will find another case where it fails to produce a reasonable result.
Also, this section of code, i.e. trying to decode floats, has already been changed and fixed several times before (#22478, 8f6e67d and #32438), so it's not that easy to get it right and consider all edge cases. Maybe it would be better to try a different approach, something like #36482 or similar?
Btw, I assume we don't want to support comma as decimal separator.
Additional context
Normally I would say it's a limitation of the XmlEncoder, but returning a string only for floats which start with zero - it might be super confusing and difficult to debug.
For example (actually, that's how I found it), if you have a method which accepts floats (type hinting it) and receives as arguments values decoded by XmlEncoder, and the XML data looks like this:
...
<foo bar="1.9558"/>
<foo bar="25.653"/>
<foo bar="7.4615"/>
<foo bar="0.86828"/>
<foo bar="317.62"/>
...
The process will be sometimes failing, but it will look very randomly. Looking at the data, everything seems to be valid.