properly handle null data when denormalizing

If null is passed to denormalize(), no property values can be set on
the denormalized object. Additionally, this fixes passing values to
the denormalized object's constructor if the incoming data is an object.
This commit is contained in:
Christian Flothmann 2014-07-20 16:43:00 +02:00
parent 9572918064
commit 123fc62652
2 changed files with 48 additions and 4 deletions

View File

@ -114,6 +114,18 @@ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements Normal
*/ */
public function denormalize($data, $class, $format = null, array $context = array()) public function denormalize($data, $class, $format = null, array $context = array())
{ {
if (is_array($data) || is_object($data) && $data instanceof \ArrayAccess) {
$normalizedData = $data;
} elseif (is_object($data)) {
$normalizedData = array();
foreach ($data as $attribute => $value) {
$normalizedData[$attribute] = $value;
}
} else {
$normalizedData = array();
}
$reflectionClass = new \ReflectionClass($class); $reflectionClass = new \ReflectionClass($class);
$constructor = $reflectionClass->getConstructor(); $constructor = $reflectionClass->getConstructor();
@ -124,10 +136,10 @@ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements Normal
foreach ($constructorParameters as $constructorParameter) { foreach ($constructorParameters as $constructorParameter) {
$paramName = lcfirst($this->formatAttribute($constructorParameter->name)); $paramName = lcfirst($this->formatAttribute($constructorParameter->name));
if (isset($data[$paramName])) { if (isset($normalizedData[$paramName])) {
$params[] = $data[$paramName]; $params[] = $normalizedData[$paramName];
// don't run set for a parameter passed to the constructor // don't run set for a parameter passed to the constructor
unset($data[$paramName]); unset($normalizedData[$paramName]);
} elseif ($constructorParameter->isOptional()) { } elseif ($constructorParameter->isOptional()) {
$params[] = $constructorParameter->getDefaultValue(); $params[] = $constructorParameter->getDefaultValue();
} else { } else {
@ -144,7 +156,7 @@ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements Normal
$object = new $class; $object = new $class;
} }
foreach ($data as $attribute => $value) { foreach ($normalizedData as $attribute => $value) {
$setter = 'set'.$this->formatAttribute($attribute); $setter = 'set'.$this->formatAttribute($attribute);
if (method_exists($object, $setter)) { if (method_exists($object, $setter)) {

View File

@ -15,6 +15,11 @@ use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
{ {
/**
* @var GetSetMethodNormalizer
*/
private $normalizer;
protected function setUp() protected function setUp()
{ {
$this->normalizer = new GetSetMethodNormalizer(); $this->normalizer = new GetSetMethodNormalizer();
@ -44,6 +49,17 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('bar', $obj->getBar()); $this->assertEquals('bar', $obj->getBar());
} }
public function testDenormalizeWithObject()
{
$data = new \stdClass();
$data->foo = 'foo';
$data->bar = 'bar';
$data->fooBar = 'foobar';
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetSetDummy', 'any');
$this->assertEquals('foo', $obj->getFoo());
$this->assertEquals('bar', $obj->getBar());
}
public function testDenormalizeOnCamelCaseFormat() public function testDenormalizeOnCamelCaseFormat()
{ {
$this->normalizer->setCamelizedAttributes(array('camel_case')); $this->normalizer->setCamelizedAttributes(array('camel_case'));
@ -54,6 +70,11 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('camelCase', $obj->getCamelCase()); $this->assertEquals('camelCase', $obj->getCamelCase());
} }
public function testDenormalizeNull()
{
$this->assertEquals(new GetSetDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\GetSetDummy'));
}
/** /**
* @dataProvider attributeProvider * @dataProvider attributeProvider
*/ */
@ -96,6 +117,17 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array(1, 2, 3), $obj->getBaz()); $this->assertEquals(array(1, 2, 3), $obj->getBaz());
} }
public function testConstructorWithObjectDenormalize()
{
$data = new \stdClass();
$data->foo = 'foo';
$data->bar = 'bar';
$data->fooBar = 'foobar';
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetConstructorDummy', 'any');
$this->assertEquals('foo', $obj->getFoo());
$this->assertEquals('bar', $obj->getBar());
}
/** /**
* @dataProvider provideCallbacks * @dataProvider provideCallbacks
*/ */