[Serializer] int is valid when float is expected when deserializing JSON
This commit is contained in:
parent
c3a50b0931
commit
4125455775
|
@ -12,6 +12,7 @@
|
|||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||
use Symfony\Component\Serializer\Exception\CircularReferenceException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
@ -260,6 +261,16 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
|||
}
|
||||
}
|
||||
|
||||
// JSON only has a Number type corresponding to both int and float PHP types.
|
||||
// PHP's json_encode, JavaScript's JSON.stringify, Go's json.Marshal as well as most other JSON encoders convert
|
||||
// floating-point numbers like 12.0 to 12 (the decimal part is dropped when possible).
|
||||
// PHP's json_decode automatically converts Numbers without a decimal part to integers.
|
||||
// To circumvent this behavior, integers are converted to floats when denormalizing JSON based formats and when
|
||||
// a float is expected.
|
||||
if (Type::BUILTIN_TYPE_FLOAT === $builtinType && is_int($data) && false !== strpos($format, JsonEncoder::FORMAT)) {
|
||||
return (float) $data;
|
||||
}
|
||||
|
||||
if (call_user_func('is_'.$builtinType, $data)) {
|
||||
return $data;
|
||||
}
|
||||
|
|
|
@ -537,11 +537,21 @@ class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
|
|||
'inners' => array(array('foo' => 1), array('foo' => 2)),
|
||||
), ObjectOuter::class);
|
||||
|
||||
$this->assertEquals('foo', $obj->getInner()->foo);
|
||||
$this->assertEquals('bar', $obj->getInner()->bar);
|
||||
$this->assertEquals('1988-01-21', $obj->getDate()->format('Y-m-d'));
|
||||
$this->assertEquals(1, $obj->getInners()[0]->foo);
|
||||
$this->assertEquals(2, $obj->getInners()[1]->foo);
|
||||
$this->assertSame('foo', $obj->getInner()->foo);
|
||||
$this->assertSame('bar', $obj->getInner()->bar);
|
||||
$this->assertSame('1988-01-21', $obj->getDate()->format('Y-m-d'));
|
||||
$this->assertSame(1, $obj->getInners()[0]->foo);
|
||||
$this->assertSame(2, $obj->getInners()[1]->foo);
|
||||
}
|
||||
|
||||
public function testAcceptJsonNumber()
|
||||
{
|
||||
$extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor()));
|
||||
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
|
||||
$serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer));
|
||||
|
||||
$this->assertSame(10.0, $serializer->denormalize(array('number' => 10), JsonNumber::class, 'json')->number);
|
||||
$this->assertSame(10.0, $serializer->denormalize(array('number' => 10), JsonNumber::class, 'jsonld')->number);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -820,3 +830,11 @@ class FormatAndContextAwareNormalizer extends ObjectNormalizer
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class JsonNumber
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $number;
|
||||
}
|
||||
|
|
Reference in New Issue