Skip to content

Commit 9ff8dfd

Browse files
committed
Completly refactor the Serializer Options Pull Request to push context information directly and avoid state and dependencies between SerializerInterface and encoders/normalizers.
1 parent 8278f31 commit 9ff8dfd

21 files changed

+113
-160
lines changed

Encoder/ChainDecoder.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ public function __construct(array $decoders = array())
3434
/**
3535
* {@inheritdoc}
3636
*/
37-
final public function decode($data, $format)
37+
final public function decode($data, $format, array $context = array())
3838
{
39-
return $this->getDecoder($format)->decode($data, $format);
39+
return $this->getDecoder($format)->decode($data, $format, $context);
4040
}
4141

4242
/**

Encoder/ChainEncoder.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ public function __construct(array $encoders = array())
3535
/**
3636
* {@inheritdoc}
3737
*/
38-
final public function encode($data, $format)
38+
final public function encode($data, $format, array $context = array())
3939
{
40-
return $this->getEncoder($format)->encode($data, $format);
40+
return $this->getEncoder($format)->encode($data, $format, $context);
4141
}
4242

4343
/**

Encoder/DecoderInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ interface DecoderInterface
2323
*
2424
* @param scalar $data Data to decode
2525
* @param string $format Format name
26+
* @param array $context options that decoders have access to.
2627
*
2728
* @return mixed
2829
*/
29-
public function decode($data, $format);
30+
public function decode($data, $format, array $context = array());
3031

3132
/**
3233
* Checks whether the serializer can decode from given format

Encoder/EncoderInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ interface EncoderInterface
2323
*
2424
* @param mixed $data Data to encode
2525
* @param string $format Format name
26+
* @param array $context options that normalizers/encoders have access to.
2627
*
2728
* @return scalar
2829
*/
29-
public function encode($data, $format);
30+
public function encode($data, $format, array $context = array());
3031

3132
/**
3233
* Checks whether the serializer can encode to given format

Encoder/JsonDecode.php

Lines changed: 16 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,12 @@
1111

1212
namespace Symfony\Component\Serializer\Encoder;
1313

14-
use Symfony\Component\Serializer\SerializerInterface;
15-
use Symfony\Component\Serializer\SerializerAwareInterface;
16-
1714
/**
1815
* Decodes JSON data
1916
*
2017
* @author Sander Coolen <sander@jibber.nl>
2118
*/
22-
class JsonDecode implements DecoderInterface, SerializerAwareInterface
19+
class JsonDecode implements DecoderInterface
2320
{
2421
private $associative;
2522
private $recursionDepth;
@@ -52,13 +49,13 @@ public function getLastError()
5249
*
5350
* @return mixed
5451
*/
55-
public function decode($data, $format)
52+
public function decode($data, $format, array $context = array())
5653
{
57-
$context = $this->getContext();
54+
$context = $this->resolveContext($context);
5855

59-
$associative = $context['associative'];
60-
$recursionDepth = $context['recursionDepth'];
61-
$options = $context['options'];
56+
$associative = $context['json_decode_associative'];
57+
$recursionDepth = $context['json_decode_recursion_depth'];
58+
$options = $context['json_decode_options'];
6259

6360
$decodedData = json_decode($data, $associative, $recursionDepth, $options);
6461
$this->lastError = json_last_error();
@@ -75,45 +72,19 @@ public function supportsDecoding($format)
7572
}
7673

7774
/**
78-
* {@inheritdoc}
75+
* Merge the default options of the Json Decoder with the passed context.
76+
*
77+
* @param array $context
78+
* @return array
7979
*/
80-
public function setSerializer(SerializerInterface $serializer)
80+
private function resolveContext(array $context)
8181
{
82-
$this->serializer = $serializer;
83-
}
84-
85-
private function getContext()
86-
{
87-
$options = array(
88-
'associative' => $this->associative,
89-
'recursionDepth' => $this->recursionDepth,
90-
'options' => 0
82+
$defaultOptions = array(
83+
'json_decode_associative' => $this->associative,
84+
'json_decode_recursion_depth' => $this->recursionDepth,
85+
'json_decode_options' => 0
9186
);
9287

93-
if (!$this->serializer) {
94-
return $options;
95-
}
96-
97-
$options = array(
98-
'associative' => false,
99-
'recursionDepth' => 512,
100-
'options' => 0
101-
);
102-
103-
$context = $this->serializer->getContext();
104-
105-
if (isset($context['associative'])) {
106-
$options['associative'] = $context['associative'];
107-
}
108-
109-
if (isset($context['recursionDepth'])) {
110-
$options['recursionDepth'] = $context['recursionDepth'];
111-
}
112-
113-
if (isset($context['options'])) {
114-
$options['options'] = $context['options'];
115-
}
116-
117-
return $options;
88+
return array_merge($defaultOptions, $context);
11889
}
11990
}

Encoder/JsonEncode.php

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @author Sander Coolen <sander@jibber.nl>
1818
*/
19-
class JsonEncode extends SerializerAwareEncoder implements EncoderInterface
19+
class JsonEncode implements EncoderInterface
2020
{
2121
private $options ;
2222
private $lastError = JSON_ERROR_NONE;
@@ -41,16 +41,13 @@ public function getLastError()
4141
/**
4242
* Encodes PHP data to a JSON string
4343
*
44-
* @param mixed $data
45-
* @param string $format
46-
*
47-
* @return string
44+
* {@inheritdoc}
4845
*/
49-
public function encode($data, $format)
46+
public function encode($data, $format, array $context = array())
5047
{
51-
$options = $this->getContext();
48+
$context = $this->resolveContext($context);
5249

53-
$encodedJson = json_encode($data, $options);
50+
$encodedJson = json_encode($data, $context['json_encode_options']);
5451
$this->lastError = json_last_error();
5552

5653
return $encodedJson;
@@ -64,22 +61,14 @@ public function supportsEncoding($format)
6461
return JsonEncoder::FORMAT === $format;
6562
}
6663

67-
private function getContext()
64+
/**
65+
* Merge default json encode options with context.
66+
*
67+
* @param array $context
68+
* @return array
69+
*/
70+
private function resolveContext(array $context = array())
6871
{
69-
if (!$this->serializer) {
70-
return 0;
71-
}
72-
73-
$context = $this->serializer->getContext();
74-
75-
if (empty($context)) {
76-
$context = array(0);
77-
}
78-
79-
if (!is_array($context)) {
80-
$context = array($context);
81-
}
82-
83-
return array_sum($context);
72+
return array_merge(array('json_encode_options' => $this->options), $context);
8473
}
8574
}

Encoder/JsonEncoder.php

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @author Jordi Boggiano <j.boggiano@seld.be>
1818
*/
19-
class JsonEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface
19+
class JsonEncoder implements EncoderInterface, DecoderInterface
2020
{
2121
const FORMAT = 'json';
2222

@@ -59,21 +59,17 @@ public function getLastDecodingError()
5959
/**
6060
* {@inheritdoc}
6161
*/
62-
public function encode($data, $format)
62+
public function encode($data, $format, array $context = array())
6363
{
64-
$this->encodingImpl->setSerializer($this->serializer);
65-
66-
return $this->encodingImpl->encode($data, self::FORMAT);
64+
return $this->encodingImpl->encode($data, self::FORMAT, $context);
6765
}
6866

6967
/**
7068
* {@inheritdoc}
7169
*/
72-
public function decode($data, $format)
70+
public function decode($data, $format, array $context = array())
7371
{
74-
$this->decodingImpl->setSerializer($this->serializer);
75-
76-
return $this->decodingImpl->decode($data, self::FORMAT);
72+
return $this->decodingImpl->decode($data, self::FORMAT, $context);
7773
}
7874

7975
/**

Encoder/XmlEncoder.php

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,36 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec
2626
private $format;
2727
private $rootNodeName = 'response';
2828

29+
/**
30+
* Construct new XmlEncoder and allow to change the root node element name.
31+
*
32+
* @param string $rootNodeName
33+
*/
34+
public function __construct($rootNodeName = 'response')
35+
{
36+
$this->rootNodeName = $rootNodeName;
37+
}
38+
2939
/**
3040
* {@inheritdoc}
3141
*/
32-
public function encode($data, $format)
42+
public function encode($data, $format, array $context = array())
3343
{
3444
if ($data instanceof \DOMDocument) {
3545
return $data->saveXML();
3646
}
3747

48+
$xmlRootNodeName = $this->resolveXmlRootName($context);
49+
3850
$this->dom = new \DOMDocument();
3951
$this->format = $format;
4052

4153
if (null !== $data && !is_scalar($data)) {
42-
$root = $this->dom->createElement($this->getRealRootNodeName());
54+
$root = $this->dom->createElement($xmlRootNodeName);
4355
$this->dom->appendChild($root);
44-
$this->buildXml($root, $data);
56+
$this->buildXml($root, $data, $xmlRootNodeName);
4557
} else {
46-
$this->appendNode($this->dom, $data, $this->getRealRootNodeName());
58+
$this->appendNode($this->dom, $data, $xmlRootNodeName);
4759
}
4860

4961
return $this->dom->saveXML();
@@ -52,7 +64,7 @@ public function encode($data, $format)
5264
/**
5365
* {@inheritdoc}
5466
*/
55-
public function decode($data, $format)
67+
public function decode($data, $format, array $context = array())
5668
{
5769
$internalErrors = libxml_use_internal_errors(true);
5870
$disableEntities = libxml_disable_entity_loader(true);
@@ -269,12 +281,13 @@ private function parseXml($node)
269281
*
270282
* @param DOMNode $parentNode
271283
* @param array|object $data data
284+
* @param string $xmlRootNodeName
272285
*
273286
* @return Boolean
274287
*
275288
* @throws UnexpectedValueException
276289
*/
277-
private function buildXml($parentNode, $data)
290+
private function buildXml($parentNode, $data, $xmlRootNodeName)
278291
{
279292
$append = true;
280293

@@ -310,21 +323,24 @@ private function buildXml($parentNode, $data)
310323

311324
return $append;
312325
}
326+
313327
if (is_object($data)) {
314328
$data = $this->serializer->normalize($data, $this->format);
315329
if (null !== $data && !is_scalar($data)) {
316-
return $this->buildXml($parentNode, $data);
330+
return $this->buildXml($parentNode, $data, $xmlRootNodeName);
317331
}
332+
318333
// top level data object was normalized into a scalar
319334
if (!$parentNode->parentNode->parentNode) {
320335
$root = $parentNode->parentNode;
321336
$root->removeChild($parentNode);
322337

323-
return $this->appendNode($root, $data, $this->getRealRootNodeName());
338+
return $this->appendNode($root, $data, $xmlRootNodeName);
324339
}
325340

326341
return $this->appendNode($parentNode, $data, 'data');
327342
}
343+
328344
throw new UnexpectedValueException('An unexpected value could not be serialized: '.var_export($data, true));
329345
}
330346

@@ -376,7 +392,7 @@ private function needsCdataWrapping($val)
376392
private function selectNodeType($node, $val)
377393
{
378394
if (is_array($val)) {
379-
return $this->buildXml($node, $val);
395+
return $this->buildXml($node, $val, null);
380396
} elseif ($val instanceof \SimpleXMLElement) {
381397
$child = $this->dom->importNode(dom_import_simplexml($val), true);
382398
$node->appendChild($child);
@@ -403,14 +419,8 @@ private function selectNodeType($node, $val)
403419
/**
404420
* Get real XML root node name, taking serializer options into account.
405421
*/
406-
private function getRealRootNodeName()
422+
private function resolveXmlRootName(array $context = array())
407423
{
408-
if (!$this->serializer) {
409-
return $this->rootNodeName;
410-
}
411-
412-
$context = $this->serializer->getContext();
413-
414424
return isset($context['xml_root_node_name'])
415425
? $context['xml_root_node_name']
416426
: $this->rootNodeName;

Normalizer/CustomNormalizer.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ class CustomNormalizer extends SerializerAwareNormalizer implements NormalizerIn
1919
/**
2020
* {@inheritdoc}
2121
*/
22-
public function normalize($object, $format = null)
22+
public function normalize($object, $format = null, array $context = array())
2323
{
24-
return $object->normalize($this->serializer, $format);
24+
return $object->normalize($this->serializer, $format, $context);
2525
}
2626

2727
/**
2828
* {@inheritdoc}
2929
*/
30-
public function denormalize($data, $class, $format = null)
30+
public function denormalize($data, $class, $format = null, array $context = array())
3131
{
3232
$object = new $class;
33-
$object->denormalize($this->serializer, $data, $format);
33+
$object->denormalize($this->serializer, $data, $format, $context);
3434

3535
return $object;
3636
}

Normalizer/DenormalizableInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface DenormalizableInterface
3232
* @param array|scalar $data The data from which to re-create the object.
3333
* @param string|null $format The format is optionally given to be able to denormalize differently
3434
* based on different input formats.
35+
* @param array $context options for denormalizing
3536
*/
36-
public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null);
37+
public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array());
3738
}

0 commit comments

Comments
 (0)