Permalink
Browse files

Completly refactor the Serializer Options Pull Request to push contex…

…t information directly and avoid state and dependencies between SerializerInterface and encoders/normalizers.
  • Loading branch information...
1 parent ef652e2 commit b6bdb450e3b849c8adfc6732c16c0c7de84a8fb0 @beberlei beberlei committed Jan 18, 2013
Showing with 119 additions and 160 deletions.
  1. +6 −0 UPGRADE-2.2.md
  2. +2 −2 src/Symfony/Component/Serializer/Encoder/ChainDecoder.php
  3. +2 −2 src/Symfony/Component/Serializer/Encoder/ChainEncoder.php
  4. +2 −1 src/Symfony/Component/Serializer/Encoder/DecoderInterface.php
  5. +2 −1 src/Symfony/Component/Serializer/Encoder/EncoderInterface.php
  6. +16 −45 src/Symfony/Component/Serializer/Encoder/JsonDecode.php
  7. +13 −24 src/Symfony/Component/Serializer/Encoder/JsonEncode.php
  8. +5 −9 src/Symfony/Component/Serializer/Encoder/JsonEncoder.php
  9. +26 −16 src/Symfony/Component/Serializer/Encoder/XmlEncoder.php
  10. +4 −4 src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php
  11. +2 −1 src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php
  12. +2 −1 src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php
  13. +2 −2 src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php
  14. +2 −1 src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php
  15. +2 −1 src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php
  16. +23 −34 src/Symfony/Component/Serializer/Serializer.php
  17. +0 −7 src/Symfony/Component/Serializer/SerializerInterface.php
  18. +1 −2 src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php
  19. +1 −1 src/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php
  20. +2 −2 src/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php
  21. +2 −2 src/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php
  22. +2 −2 src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php
View
@@ -383,3 +383,9 @@
framework:
trusted_proxies: ['127.0.0.1', '10.0.0.1'] # a list of proxy IPs you trust
```
+
+#### Serializer
+
+ * All serializer interfaces (Serializer, Normalizer, Encoder) have been extended with an optional ``$context`` array.
+ This was necessary to allow for more complex use-cases that require context information during the (de)normalization
+ and en-/decoding steps.
@@ -34,9 +34,9 @@ public function __construct(array $decoders = array())
/**
* {@inheritdoc}
*/
- final public function decode($data, $format)
+ final public function decode($data, $format, array $context = array())
{
- return $this->getDecoder($format)->decode($data, $format);
+ return $this->getDecoder($format)->decode($data, $format, $context);
}
/**
@@ -35,9 +35,9 @@ public function __construct(array $encoders = array())
/**
* {@inheritdoc}
*/
- final public function encode($data, $format)
+ final public function encode($data, $format, array $context = array())
{
- return $this->getEncoder($format)->encode($data, $format);
+ return $this->getEncoder($format)->encode($data, $format, $context);
}
/**
@@ -23,10 +23,11 @@
*
* @param scalar $data Data to decode
* @param string $format Format name
+ * @param array $context options that decoders have access to.
*
* @return mixed
*/
- public function decode($data, $format);
+ public function decode($data, $format, array $context = array());
/**
* Checks whether the serializer can decode from given format
@@ -23,10 +23,11 @@
*
* @param mixed $data Data to encode
* @param string $format Format name
+ * @param array $context options that normalizers/encoders have access to.
*
* @return scalar
*/
- public function encode($data, $format);
+ public function encode($data, $format, array $context = array());
/**
* Checks whether the serializer can encode to given format
@@ -11,15 +11,12 @@
namespace Symfony\Component\Serializer\Encoder;
-use Symfony\Component\Serializer\SerializerInterface;
-use Symfony\Component\Serializer\SerializerAwareInterface;
-
/**
* Decodes JSON data
*
* @author Sander Coolen <sander@jibber.nl>
*/
-class JsonDecode implements DecoderInterface, SerializerAwareInterface
+class JsonDecode implements DecoderInterface
{
private $associative;
private $recursionDepth;
@@ -52,13 +49,13 @@ public function getLastError()
*
* @return mixed
*/
- public function decode($data, $format)
+ public function decode($data, $format, array $context = array())
{
- $context = $this->getContext();
+ $context = $this->resolveContext($context);
- $associative = $context['associative'];
- $recursionDepth = $context['recursionDepth'];
- $options = $context['options'];
+ $associative = $context['json_decode_associative'];
+ $recursionDepth = $context['json_decode_recursion_depth'];
+ $options = $context['json_decode_options'];
$decodedData = json_decode($data, $associative, $recursionDepth, $options);
$this->lastError = json_last_error();
@@ -75,45 +72,19 @@ public function supportsDecoding($format)
}
/**
- * {@inheritdoc}
+ * Merge the default options of the Json Decoder with the passed context.
+ *
+ * @param array $context
+ * @return array
*/
- public function setSerializer(SerializerInterface $serializer)
+ private function resolveContext(array $context)
{
- $this->serializer = $serializer;
- }
-
- private function getContext()
- {
- $options = array(
- 'associative' => $this->associative,
- 'recursionDepth' => $this->recursionDepth,
- 'options' => 0
+ $defaultOptions = array(
+ 'json_decode_associative' => $this->associative,
+ 'json_decode_recursion_depth' => $this->recursionDepth,
+ 'json_decode_options' => 0
);
- if (!$this->serializer) {
- return $options;
- }
-
- $options = array(
- 'associative' => false,
- 'recursionDepth' => 512,
- 'options' => 0
- );
-
- $context = $this->serializer->getContext();
-
- if (isset($context['associative'])) {
- $options['associative'] = $context['associative'];
- }
-
- if (isset($context['recursionDepth'])) {
- $options['recursionDepth'] = $context['recursionDepth'];
- }
-
- if (isset($context['options'])) {
- $options['options'] = $context['options'];
- }
-
- return $options;
+ return array_merge($defaultOptions, $context);
}
}
@@ -16,7 +16,7 @@
*
* @author Sander Coolen <sander@jibber.nl>
*/
-class JsonEncode extends SerializerAwareEncoder implements EncoderInterface
+class JsonEncode implements EncoderInterface
{
private $options ;
private $lastError = JSON_ERROR_NONE;
@@ -41,16 +41,13 @@ public function getLastError()
/**
* Encodes PHP data to a JSON string
*
- * @param mixed $data
- * @param string $format
- *
- * @return string
+ * {@inheritdoc}
*/
- public function encode($data, $format)
+ public function encode($data, $format, array $context = array())
{
- $options = $this->getContext();
+ $context = $this->resolveContext($context);
- $encodedJson = json_encode($data, $options);
+ $encodedJson = json_encode($data, $context['json_encode_options']);
$this->lastError = json_last_error();
return $encodedJson;
@@ -64,22 +61,14 @@ public function supportsEncoding($format)
return JsonEncoder::FORMAT === $format;
}
- private function getContext()
+ /**
+ * Merge default json encode options with context.
+ *
+ * @param array $context
+ * @return array
+ */
+ private function resolveContext(array $context = array())
{
- if (!$this->serializer) {
- return 0;
- }
-
- $context = $this->serializer->getContext();
-
- if (empty($context)) {
- $context = array(0);
- }
-
- if (!is_array($context)) {
- $context = array($context);
- }
-
- return array_sum($context);
+ return array_merge(array('json_encode_options' => $this->options), $context);
}
}
@@ -16,7 +16,7 @@
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
-class JsonEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface
+class JsonEncoder implements EncoderInterface, DecoderInterface
{
const FORMAT = 'json';
@@ -59,21 +59,17 @@ public function getLastDecodingError()
/**
* {@inheritdoc}
*/
- public function encode($data, $format)
+ public function encode($data, $format, array $context = array())
{
- $this->encodingImpl->setSerializer($this->serializer);
-
- return $this->encodingImpl->encode($data, self::FORMAT);
+ return $this->encodingImpl->encode($data, self::FORMAT, $context);
}
/**
* {@inheritdoc}
*/
- public function decode($data, $format)
+ public function decode($data, $format, array $context = array())
{
- $this->decodingImpl->setSerializer($this->serializer);
-
- return $this->decodingImpl->decode($data, self::FORMAT);
+ return $this->decodingImpl->decode($data, self::FORMAT, $context);
}
/**
@@ -27,23 +27,35 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec
private $rootNodeName = 'response';
/**
+ * Construct new XmlEncoder and allow to change the root node element name.
+ *
+ * @param string $rootNodeName
+ */
+ public function __construct($rootNodeName = 'response')
+ {
+ $this->rootNodeName = $rootNodeName;
+ }
+
+ /**
* {@inheritdoc}
*/
- public function encode($data, $format)
+ public function encode($data, $format, array $context = array())
{
if ($data instanceof \DOMDocument) {
return $data->saveXML();
}
+ $xmlRootNodeName = $this->resolveXmlRootName($context);
+
$this->dom = new \DOMDocument();
$this->format = $format;
if (null !== $data && !is_scalar($data)) {
- $root = $this->dom->createElement($this->getRealRootNodeName());
+ $root = $this->dom->createElement($xmlRootNodeName);
$this->dom->appendChild($root);
- $this->buildXml($root, $data);
+ $this->buildXml($root, $data, $xmlRootNodeName);
} else {
- $this->appendNode($this->dom, $data, $this->getRealRootNodeName());
+ $this->appendNode($this->dom, $data, $xmlRootNodeName);
}
return $this->dom->saveXML();
@@ -52,7 +64,7 @@ public function encode($data, $format)
/**
* {@inheritdoc}
*/
- public function decode($data, $format)
+ public function decode($data, $format, array $context = array())
{
$internalErrors = libxml_use_internal_errors(true);
$disableEntities = libxml_disable_entity_loader(true);
@@ -269,12 +281,13 @@ private function parseXml($node)
*
* @param DOMNode $parentNode
* @param array|object $data data
+ * @param string $xmlRootNodeName
*
* @return Boolean
*
* @throws UnexpectedValueException
*/
- private function buildXml($parentNode, $data)
+ private function buildXml($parentNode, $data, $xmlRootNodeName)
{
$append = true;
@@ -310,21 +323,24 @@ private function buildXml($parentNode, $data)
return $append;
}
+
if (is_object($data)) {
$data = $this->serializer->normalize($data, $this->format);
if (null !== $data && !is_scalar($data)) {
- return $this->buildXml($parentNode, $data);
+ return $this->buildXml($parentNode, $data, $xmlRootNodeName);
}
+
// top level data object was normalized into a scalar
if (!$parentNode->parentNode->parentNode) {
$root = $parentNode->parentNode;
$root->removeChild($parentNode);
- return $this->appendNode($root, $data, $this->getRealRootNodeName());
+ return $this->appendNode($root, $data, $xmlRootNodeName);
}
return $this->appendNode($parentNode, $data, 'data');
}
+
throw new UnexpectedValueException('An unexpected value could not be serialized: '.var_export($data, true));
}
@@ -376,7 +392,7 @@ private function needsCdataWrapping($val)
private function selectNodeType($node, $val)
{
if (is_array($val)) {
- return $this->buildXml($node, $val);
+ return $this->buildXml($node, $val, null);
} elseif ($val instanceof \SimpleXMLElement) {
$child = $this->dom->importNode(dom_import_simplexml($val), true);
$node->appendChild($child);
@@ -403,14 +419,8 @@ private function selectNodeType($node, $val)
/**
* Get real XML root node name, taking serializer options into account.
*/
- private function getRealRootNodeName()
+ private function resolveXmlRootName(array $context = array())
{
- if (!$this->serializer) {
- return $this->rootNodeName;
- }
-
- $context = $this->serializer->getContext();
-
return isset($context['xml_root_node_name'])
? $context['xml_root_node_name']
: $this->rootNodeName;
@@ -19,18 +19,18 @@ class CustomNormalizer extends SerializerAwareNormalizer implements NormalizerIn
/**
* {@inheritdoc}
*/
- public function normalize($object, $format = null)
+ public function normalize($object, $format = null, array $context = array())
{
- return $object->normalize($this->serializer, $format);
+ return $object->normalize($this->serializer, $format, $context);
}
/**
* {@inheritdoc}
*/
- public function denormalize($data, $class, $format = null)
+ public function denormalize($data, $class, $format = null, array $context = array())
{
$object = new $class;
- $object->denormalize($this->serializer, $data, $format);
+ $object->denormalize($this->serializer, $data, $format, $context);
return $object;
}
@@ -32,6 +32,7 @@
* @param array|scalar $data The data from which to re-create the object.
* @param string|null $format The format is optionally given to be able to denormalize differently
* based on different input formats.
+ * @param array $context options for denormalizing
*/
- public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null);
+ public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array());
}
Oops, something went wrong.

0 comments on commit b6bdb45

Please sign in to comment.