Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3331c8a

Browse files
committedJan 12, 2016
bug symfony#17199 [Serializer] Allow context to contain not serializable data (dunglas, nicolas-grekas)
This PR was merged into the 2.8 branch. Discussion ---------- [Serializer] Allow context to contain not serializable data | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Allow the context to contain not serializable data even for the `ObjectNormalizer` (BC break fix). Commits ------- 996f69d Merge pull request #2 from nicolas-grekas/ser-cache 8560c13 [Serializer] Use $context['cache_key'] to enhance caching c1740fc [Serializer] ObjectNormalizer: context can contain not serializable data
2 parents 51a5a26 + 996f69d commit 3331c8a

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed
 

‎src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php

+47-10
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*/
2727
class ObjectNormalizer extends AbstractNormalizer
2828
{
29-
private static $attributesCache = array();
29+
private $attributesCache = array();
3030

3131
/**
3232
* @var PropertyAccessorInterface
@@ -55,6 +55,9 @@ public function supportsNormalization($data, $format = null)
5555
*/
5656
public function normalize($object, $format = null, array $context = array())
5757
{
58+
if (!isset($context['cache_key'])) {
59+
$context['cache_key'] = $this->getCacheKey($context);
60+
}
5861
if ($this->isCircularReference($object, $context)) {
5962
return $this->handleCircularReference($object);
6063
}
@@ -104,6 +107,9 @@ public function supportsDenormalization($data, $type, $format = null)
104107
*/
105108
public function denormalize($data, $class, $format = null, array $context = array())
106109
{
110+
if (!isset($context['cache_key'])) {
111+
$context['cache_key'] = $this->getCacheKey($context);
112+
}
107113
$allowedAttributes = $this->getAllowedAttributes($class, $context, true);
108114
$normalizedData = $this->prepareForDenormalization($data);
109115

@@ -130,28 +136,59 @@ public function denormalize($data, $class, $format = null, array $context = arra
130136
return $object;
131137
}
132138

139+
private function getCacheKey(array $context)
140+
{
141+
try {
142+
return md5(serialize($context));
143+
} catch (\Exception $exception) {
144+
// The context cannot be serialized, skip the cache
145+
return false;
146+
}
147+
}
148+
133149
/**
134150
* Gets and caches attributes for this class and context.
135151
*
136152
* @param object $object
137153
* @param array $context
138154
*
139-
* @return array
155+
* @return string[]
140156
*/
141157
private function getAttributes($object, array $context)
142158
{
143-
$key = sprintf('%s-%s', get_class($object), serialize($context));
159+
$class = get_class($object);
160+
$key = $class.'-'.$context['cache_key'];
144161

145-
if (isset(self::$attributesCache[$key])) {
146-
return self::$attributesCache[$key];
162+
if (isset($this->attributesCache[$key])) {
163+
return $this->attributesCache[$key];
147164
}
148165

149166
$allowedAttributes = $this->getAllowedAttributes($object, $context, true);
150167

151168
if (false !== $allowedAttributes) {
152-
return self::$attributesCache[$key] = $allowedAttributes;
169+
if ($context['cache_key']) {
170+
$this->attributesCache[$key] = $allowedAttributes;
171+
}
172+
173+
return $allowedAttributes;
174+
}
175+
176+
if (isset($this->attributesCache[$class])) {
177+
return $this->attributesCache[$class];
153178
}
154179

180+
return $this->attributesCache[$class] = $this->extractAttributes($object);
181+
}
182+
183+
/**
184+
* Extracts attributes for this class and context.
185+
*
186+
* @param object $object
187+
*
188+
* @return string[]
189+
*/
190+
private function extractAttributes($object)
191+
{
155192
// If not using groups, detect manually
156193
$attributes = array();
157194

@@ -167,9 +204,9 @@ private function getAttributes($object, array $context)
167204
continue;
168205
}
169206

170-
$name = $reflMethod->getName();
207+
$name = $reflMethod->name;
171208

172-
if (strpos($name, 'get') === 0 || strpos($name, 'has') === 0) {
209+
if (0 === strpos($name, 'get') || 0 === strpos($name, 'has')) {
173210
// getters and hassers
174211
$attributes[lcfirst(substr($name, 3))] = true;
175212
} elseif (strpos($name, 'is') === 0) {
@@ -184,9 +221,9 @@ private function getAttributes($object, array $context)
184221
continue;
185222
}
186223

187-
$attributes[$reflProperty->getName()] = true;
224+
$attributes[$reflProperty->name] = true;
188225
}
189226

190-
return self::$attributesCache[$key] = array_keys($attributes);
227+
return array_keys($attributes);
191228
}
192229
}

‎src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php

+15
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,21 @@ public function testNormalizeStatic()
473473
{
474474
$this->assertEquals(array('foo' => 'K'), $this->normalizer->normalize(new ObjectWithStaticPropertiesAndMethods()));
475475
}
476+
477+
public function testNormalizeNotSerializableContext()
478+
{
479+
$objectDummy = new ObjectDummy();
480+
$expected = array(
481+
'foo' => null,
482+
'baz' => null,
483+
'fooBar' => '',
484+
'camelCase' => null,
485+
'object' => null,
486+
'bar' => null,
487+
);
488+
489+
$this->assertEquals($expected, $this->normalizer->normalize($objectDummy, null, array('not_serializable' => function () {})));
490+
}
476491
}
477492

478493
class ObjectDummy

0 commit comments

Comments
 (0)