Skip to content

Commit 2f197e8

Browse files
committed
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.
1 parent c2b6ff4 commit 2f197e8

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

Normalizer/GetSetMethodNormalizer.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,18 @@ public function normalize($object, $format = null, array $context = array())
114114
*/
115115
public function denormalize($data, $class, $format = null, array $context = array())
116116
{
117+
if (is_array($data) || is_object($data) && $data instanceof \ArrayAccess) {
118+
$normalizedData = $data;
119+
} elseif (is_object($data)) {
120+
$normalizedData = array();
121+
122+
foreach ($data as $attribute => $value) {
123+
$normalizedData[$attribute] = $value;
124+
}
125+
} else {
126+
$normalizedData = array();
127+
}
128+
117129
$reflectionClass = new \ReflectionClass($class);
118130
$constructor = $reflectionClass->getConstructor();
119131

@@ -124,10 +136,10 @@ public function denormalize($data, $class, $format = null, array $context = arra
124136
foreach ($constructorParameters as $constructorParameter) {
125137
$paramName = lcfirst($this->formatAttribute($constructorParameter->name));
126138

127-
if (isset($data[$paramName])) {
128-
$params[] = $data[$paramName];
139+
if (isset($normalizedData[$paramName])) {
140+
$params[] = $normalizedData[$paramName];
129141
// don't run set for a parameter passed to the constructor
130-
unset($data[$paramName]);
142+
unset($normalizedData[$paramName]);
131143
} elseif ($constructorParameter->isOptional()) {
132144
$params[] = $constructorParameter->getDefaultValue();
133145
} else {
@@ -144,7 +156,7 @@ public function denormalize($data, $class, $format = null, array $context = arra
144156
$object = new $class;
145157
}
146158

147-
foreach ($data as $attribute => $value) {
159+
foreach ($normalizedData as $attribute => $value) {
148160
$setter = 'set'.$this->formatAttribute($attribute);
149161

150162
if (method_exists($object, $setter)) {

Tests/Normalizer/GetSetMethodNormalizerTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515

1616
class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
1717
{
18+
/**
19+
* @var GetSetMethodNormalizer
20+
*/
21+
private $normalizer;
22+
1823
protected function setUp()
1924
{
2025
$this->normalizer = new GetSetMethodNormalizer();
@@ -44,6 +49,17 @@ public function testDenormalize()
4449
$this->assertEquals('bar', $obj->getBar());
4550
}
4651

52+
public function testDenormalizeWithObject()
53+
{
54+
$data = new \stdClass();
55+
$data->foo = 'foo';
56+
$data->bar = 'bar';
57+
$data->fooBar = 'foobar';
58+
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetSetDummy', 'any');
59+
$this->assertEquals('foo', $obj->getFoo());
60+
$this->assertEquals('bar', $obj->getBar());
61+
}
62+
4763
public function testDenormalizeOnCamelCaseFormat()
4864
{
4965
$this->normalizer->setCamelizedAttributes(array('camel_case'));
@@ -54,6 +70,11 @@ public function testDenormalizeOnCamelCaseFormat()
5470
$this->assertEquals('camelCase', $obj->getCamelCase());
5571
}
5672

73+
public function testDenormalizeNull()
74+
{
75+
$this->assertEquals(new GetSetDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\GetSetDummy'));
76+
}
77+
5778
/**
5879
* @dataProvider attributeProvider
5980
*/
@@ -96,6 +117,17 @@ public function testConstructorDenormalizeWithMissingOptionalArgument()
96117
$this->assertEquals(array(1, 2, 3), $obj->getBaz());
97118
}
98119

120+
public function testConstructorWithObjectDenormalize()
121+
{
122+
$data = new \stdClass();
123+
$data->foo = 'foo';
124+
$data->bar = 'bar';
125+
$data->fooBar = 'foobar';
126+
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetConstructorDummy', 'any');
127+
$this->assertEquals('foo', $obj->getFoo());
128+
$this->assertEquals('bar', $obj->getBar());
129+
}
130+
99131
/**
100132
* @dataProvider provideCallbacks
101133
*/

0 commit comments

Comments
 (0)