diff --git a/UPGRADE-2.2.md b/UPGRADE-2.2.md index 5390f90acf..f46b514501 100644 --- a/UPGRADE-2.2.md +++ b/UPGRADE-2.2.md @@ -562,3 +562,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. diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index de46533563..c2dbbb7f49 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -1,6 +1,16 @@ CHANGELOG ========= +2.2.0 +----- + + * All Serializer, Normalizer and Encoder interfaces have been + modified to include an optional ``$context`` array parameter. + * The XML Root name can now be configured with the ``xml_root_name`` + parameter in the context option to the ``XmlEncoder``. + * Options to ``json_encode`` and ``json_decode`` can be passed through + the context options of ``JsonEncode`` and ``JsonDecode`` encoder/decoders. + 2.1.0 ----- diff --git a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php index f555c6a8c9..6ece3b2205 100644 --- a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php +++ b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php @@ -34,9 +34,9 @@ class ChainDecoder implements DecoderInterface /** * {@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); } /** diff --git a/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php b/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php index ebb81efb9f..bd10a2ad41 100644 --- a/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php @@ -35,9 +35,9 @@ class ChainEncoder implements EncoderInterface /** * {@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); } /** diff --git a/src/Symfony/Component/Serializer/Encoder/DecoderInterface.php b/src/Symfony/Component/Serializer/Encoder/DecoderInterface.php index e95271f740..ffd221fe8d 100644 --- a/src/Symfony/Component/Serializer/Encoder/DecoderInterface.php +++ b/src/Symfony/Component/Serializer/Encoder/DecoderInterface.php @@ -23,10 +23,11 @@ interface DecoderInterface * * @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 diff --git a/src/Symfony/Component/Serializer/Encoder/EncoderInterface.php b/src/Symfony/Component/Serializer/Encoder/EncoderInterface.php index 4a68ad3fe9..2290db7f50 100644 --- a/src/Symfony/Component/Serializer/Encoder/EncoderInterface.php +++ b/src/Symfony/Component/Serializer/Encoder/EncoderInterface.php @@ -23,10 +23,11 @@ interface EncoderInterface * * @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 diff --git a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php index 7ed8039eed..e7cd9e073d 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php @@ -21,6 +21,7 @@ class JsonDecode implements DecoderInterface private $associative; private $recursionDepth; private $lastError = JSON_ERROR_NONE; + protected $serializer; public function __construct($associative = false, $depth = 512) { @@ -48,9 +49,20 @@ class JsonDecode implements DecoderInterface * * @return mixed */ - public function decode($data, $format) + public function decode($data, $format, array $context = array()) { - $decodedData = json_decode($data, $this->associative, $this->recursionDepth); + $context = $this->resolveContext($context); + + $associative = $context['json_decode_associative']; + $recursionDepth = $context['json_decode_recursion_depth']; + $options = $context['json_decode_options']; + + if (version_compare(PHP_VERSION, '5.4.0') >= 0) { + $decodedData = json_decode($data, $associative, $recursionDepth, $options); + } else { + $decodedData = json_decode($data, $associative, $recursionDepth); + } + $this->lastError = json_last_error(); return $decodedData; @@ -63,4 +75,21 @@ class JsonDecode implements DecoderInterface { return JsonEncoder::FORMAT === $format; } + + /** + * Merge the default options of the Json Decoder with the passed context. + * + * @param array $context + * @return array + */ + private function resolveContext(array $context) + { + $defaultOptions = array( + 'json_decode_associative' => $this->associative, + 'json_decode_recursion_depth' => $this->recursionDepth, + 'json_decode_options' => 0 + ); + + return array_merge($defaultOptions, $context); + } } diff --git a/src/Symfony/Component/Serializer/Encoder/JsonEncode.php b/src/Symfony/Component/Serializer/Encoder/JsonEncode.php index 280b8a9733..4e0de3ed75 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonEncode.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonEncode.php @@ -41,14 +41,13 @@ class JsonEncode implements EncoderInterface /** * 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()) { - $encodedJson = json_encode($data, $this->options); + $context = $this->resolveContext($context); + + $encodedJson = json_encode($data, $context['json_encode_options']); $this->lastError = json_last_error(); return $encodedJson; @@ -61,4 +60,15 @@ class JsonEncode implements EncoderInterface { return JsonEncoder::FORMAT === $format; } + + /** + * Merge default json encode options with context. + * + * @param array $context + * @return array + */ + private function resolveContext(array $context = array()) + { + return array_merge(array('json_encode_options' => $this->options), $context); + } } diff --git a/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php b/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php index 73918b7051..02b179bc91 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php @@ -59,17 +59,17 @@ class JsonEncoder implements EncoderInterface, DecoderInterface /** * {@inheritdoc} */ - public function encode($data, $format) + public function encode($data, $format, array $context = array()) { - 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()) { - return $this->decodingImpl->decode($data, self::FORMAT); + return $this->decodingImpl->decode($data, self::FORMAT, $context); } /** diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index 11de50af08..909b3cefe7 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -26,24 +26,36 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec private $format; 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->rootNodeName); + $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->rootNodeName); + $this->appendNode($this->dom, $data, $xmlRootNodeName); } return $this->dom->saveXML(); @@ -52,7 +64,7 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec /** * {@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 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec * * @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 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec 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->rootNodeName); + 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 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec 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); @@ -399,4 +415,15 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec return true; } + + /** + * Get real XML root node name, taking serializer options into account. + */ + private function resolveXmlRootName(array $context = array()) + { + return isset($context['xml_root_node_name']) + ? $context['xml_root_node_name'] + : $this->rootNodeName; + } + } diff --git a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php index 4510fa0b80..0ebe00fda5 100644 --- a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php @@ -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; } diff --git a/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php b/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php index 3f3bf88323..5a1b4c196b 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php @@ -32,6 +32,7 @@ interface DenormalizableInterface * @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()); } diff --git a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php index 384f9febb6..1a5ff93f75 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php @@ -24,10 +24,11 @@ interface DenormalizerInterface * @param mixed $data data to restore * @param string $class the expected class to instantiate * @param string $format format the given data was extracted from + * @param array $context options available to the denormalizer * * @return object */ - public function denormalize($data, $class, $format = null); + public function denormalize($data, $class, $format = null, array $context = array()); /** * Checks whether the given class is supported for denormalization by this normalizer diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 2c5f1b3e87..63e7a1dea9 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -69,7 +69,7 @@ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements Normal /** * {@inheritdoc} */ - public function normalize($object, $format = null) + public function normalize($object, $format = null, array $context = array()) { $reflectionObject = new \ReflectionObject($object); $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC); @@ -101,7 +101,7 @@ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements Normal /** * {@inheritdoc} */ - public function denormalize($data, $class, $format = null) + public function denormalize($data, $class, $format = null, array $context = array()) { $reflectionClass = new \ReflectionClass($class); $constructor = $reflectionClass->getConstructor(); diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php index fb77a836d8..07c3a4a8dd 100644 --- a/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php @@ -31,8 +31,9 @@ interface NormalizableInterface * can use it to normalize objects contained within this object. * @param string|null $format The format is optionally given to be able to normalize differently * based on different output formats. + * @param array $context Options for normalizing this object * * @return array|scalar */ - public function normalize(NormalizerInterface $normalizer, $format = null); + public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array()); } diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php index f0915db2b4..744307a2ba 100644 --- a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php @@ -23,10 +23,11 @@ interface NormalizerInterface * * @param object $object object to normalize * @param string $format format the normalization result will be encoded as + * @param array $context Context options for the normalizer * * @return array|scalar */ - public function normalize($object, $format = null); + public function normalize($object, $format = null, array $context = array()); /** * Checks whether the given class is supported for normalization by this normalizer diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index cad6963b16..ab6fd58b5f 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -39,8 +39,8 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz { protected $encoder; protected $decoder; - protected $normalizers = array(); - protected $normalizerCache = array(); + protected $normalizers = array(); + protected $normalizerCache = array(); protected $denormalizerCache = array(); public function __construct(array $normalizers = array(), array $encoders = array()) @@ -72,58 +72,58 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz /** * {@inheritdoc} */ - final public function serialize($data, $format) + final public function serialize($data, $format, array $context = array()) { if (!$this->supportsEncoding($format)) { throw new UnexpectedValueException('Serialization for the format '.$format.' is not supported'); } if ($this->encoder->needsNormalization($format)) { - $data = $this->normalize($data, $format); + $data = $this->normalize($data, $format, $context); } - return $this->encode($data, $format); + return $this->encode($data, $format, $context); } /** * {@inheritdoc} */ - final public function deserialize($data, $type, $format) + final public function deserialize($data, $type, $format, array $context = array()) { if (!$this->supportsDecoding($format)) { throw new UnexpectedValueException('Deserialization for the format '.$format.' is not supported'); } - $data = $this->decode($data, $format); + $data = $this->decode($data, $format, $context); - return $this->denormalize($data, $type, $format); + return $this->denormalize($data, $type, $format, $context); } /** * {@inheritdoc} */ - public function normalize($data, $format = null) + public function normalize($data, $format = null, array $context = array()) { if (null === $data || is_scalar($data)) { return $data; } if (is_object($data) && $this->supportsNormalization($data, $format)) { - return $this->normalizeObject($data, $format); + return $this->normalizeObject($data, $format, $context); } if ($data instanceof \Traversable) { $normalized = array(); foreach ($data as $key => $val) { - $normalized[$key] = $this->normalize($val, $format); + $normalized[$key] = $this->normalize($val, $format, $context); } return $normalized; } if (is_object($data)) { - return $this->normalizeObject($data, $format); + return $this->normalizeObject($data, $format, $context); } if (is_array($data)) { foreach ($data as $key => $val) { - $data[$key] = $this->normalize($val, $format); + $data[$key] = $this->normalize($val, $format, $context); } return $data; @@ -134,9 +134,9 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz /** * {@inheritdoc} */ - public function denormalize($data, $type, $format = null) + public function denormalize($data, $type, $format = null, array $context = array()) { - return $this->denormalizeObject($data, $type, $format); + return $this->denormalizeObject($data, $type, $format, $context); } /** @@ -202,17 +202,17 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz /** * {@inheritdoc} */ - final public function encode($data, $format) + final public function encode($data, $format, array $context = array()) { - return $this->encoder->encode($data, $format); + return $this->encoder->encode($data, $format, $context); } /** * {@inheritdoc} */ - final public function decode($data, $format) + final public function decode($data, $format, array $context = array()) { - return $this->decoder->decode($data, $format); + return $this->decoder->decode($data, $format, $context); } /** @@ -220,13 +220,14 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz * * @param object $object object to normalize * @param string $format format name, present to give the option to normalizers to act differently based on formats + * @param array $context The context data for this particular normalization * * @return array|scalar * * @throws LogicException * @throws UnexpectedValueException */ - private function normalizeObject($object, $format = null) + private function normalizeObject($object, $format = null, array $context = array()) { if (!$this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to normalize objects.'); @@ -234,14 +235,14 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz $class = get_class($object); if (isset($this->normalizerCache[$class][$format])) { - return $this->normalizerCache[$class][$format]->normalize($object, $format); + return $this->normalizerCache[$class][$format]->normalize($object, $format, $context); } foreach ($this->normalizers as $normalizer) { if ($normalizer->supportsNormalization($object, $format)) { $this->normalizerCache[$class][$format] = $normalizer; - return $normalizer->normalize($object, $format); + return $normalizer->normalize($object, $format, $context); } } @@ -254,27 +255,28 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz * @param mixed $data data to restore * @param string $class the expected class to instantiate * @param string $format format name, present to give the option to normalizers to act differently based on formats + * @param array $context The context data for this particular denormalization * * @return object * * @throws LogicException * @throws UnexpectedValueException */ - private function denormalizeObject($data, $class, $format = null) + private function denormalizeObject($data, $class, $format = null, array $context = array()) { if (!$this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to denormalize objects.'); } if (isset($this->denormalizerCache[$class][$format])) { - return $this->denormalizerCache[$class][$format]->denormalize($data, $class, $format); + return $this->denormalizerCache[$class][$format]->denormalize($data, $class, $format, $context); } foreach ($this->normalizers as $normalizer) { if ($normalizer->supportsDenormalization($data, $class, $format)) { $this->denormalizerCache[$class][$format] = $normalizer; - return $normalizer->denormalize($data, $class, $format); + return $normalizer->denormalize($data, $class, $format, $context); } } diff --git a/src/Symfony/Component/Serializer/SerializerInterface.php b/src/Symfony/Component/Serializer/SerializerInterface.php index 143179fe7a..d196d780a9 100644 --- a/src/Symfony/Component/Serializer/SerializerInterface.php +++ b/src/Symfony/Component/Serializer/SerializerInterface.php @@ -21,12 +21,13 @@ interface SerializerInterface /** * Serializes data in the appropriate format * - * @param mixed $data any data - * @param string $format format name + * @param mixed $data any data + * @param string $format format name + * @param array $context options normalizers/encoders have access to * * @return string */ - public function serialize($data, $format); + public function serialize($data, $format, array $context = array()); /** * Deserializes data into the given type. @@ -34,8 +35,9 @@ interface SerializerInterface * @param mixed $data * @param string $type * @param string $format + * @param array $context * * @return object */ - public function deserialize($data, $type, $format); + public function deserialize($data, $type, $format, array $context = array()); } diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php new file mode 100644 index 0000000000..c2f60728d9 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Encoder; + +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Symfony\Component\Serializer\Serializer; +use Symfony\Component\Serializer\Normalizer\CustomNormalizer; + +class JsonEncoderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + $this->encoder = new JsonEncoder; + $this->serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder())); + } + + public function testEncodeScalar() + { + $obj = new \stdClass; + $obj->foo = "foo"; + + $expected = '{"foo":"foo"}'; + + $this->assertEquals($expected, $this->encoder->encode($obj, 'json')); + } + + public function testComplexObject() + { + $obj = $this->getObject(); + + $expected = $this->getJsonSource(); + + $this->assertEquals($expected, $this->encoder->encode($obj, 'json')); + } + + public function testOptions() + { + $context = array('json_encode_options' => JSON_NUMERIC_CHECK); + + $arr = array(); + $arr['foo'] = "3"; + + $expected = '{"foo":3}'; + + $this->assertEquals($expected, $this->serializer->serialize($arr, 'json', $context)); + + $arr = array(); + $arr['foo'] = "3"; + + $expected = '{"foo":"3"}'; + + $this->assertEquals($expected, $this->serializer->serialize($arr, 'json'), 'Context should not be persistent'); + } + + + protected function getJsonSource() + { + return '{"foo":"foo","bar":["a","b"],"baz":{"key":"val","key2":"val","A B":"bar","item":[{"title":"title1"},{"title":"title2"}],"Barry":{"FooBar":{"Baz":"Ed","@id":1}}},"qux":"1"}'; + } + + protected function getObject() + { + $obj = new \stdClass; + $obj->foo = 'foo'; + $obj->bar = array('a', 'b'); + $obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar', 'item' => array(array('title' => 'title1'), array('title' => 'title2')), 'Barry' => array('FooBar' => array('Baz' => 'Ed', '@id' => 1))); + $obj->qux = "1"; + + return $obj; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php index 23cb0217a6..b23d4c7939 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -184,6 +184,23 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase $this->assertEquals($source, $this->encoder->encode($obj, 'xml')); } + public function testEncodeSerializerXmlRootNodeNameOption() + { + $options = array('xml_root_node_name' => 'test'); + $this->encoder = new XmlEncoder; + $serializer = new Serializer(array(), array('xml' => new XmlEncoder())); + $this->encoder->setSerializer($serializer); + + $array = array( + 'person' => array('@gender' => 'M', '#' => 'Peter'), + ); + + $expected = ''."\n". + 'Peter'."\n"; + + $this->assertEquals($expected, $serializer->serialize($array, 'xml', $options)); + } + public function testDecode() { $source = $this->getXmlSource(); diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php index 468d444876..09b8a52812 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php @@ -17,7 +17,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; class DenormalizableDummy implements DenormalizableInterface { - public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array()) { } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php index cdcf510df0..6b33e84374 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php @@ -23,7 +23,7 @@ class Dummy implements NormalizableInterface, DenormalizableInterface public $baz; public $qux; - public function normalize(NormalizerInterface $normalizer, $format = null) + public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array()) { return array( 'foo' => $this->foo, @@ -33,7 +33,7 @@ class Dummy implements NormalizableInterface, DenormalizableInterface ); } - public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array()) { $this->foo = $data['foo']; $this->bar = $data['bar']; diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php index ba1f924e01..3ac2fe364f 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php @@ -18,7 +18,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; class NormalizableTraversableDummy extends TraversableDummy implements NormalizableInterface, DenormalizableInterface { - public function normalize(NormalizerInterface $normalizer, $format = null) + public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array()) { return array( 'foo' => 'normalizedFoo', @@ -26,7 +26,7 @@ class NormalizableTraversableDummy extends TraversableDummy implements Normaliza ); } - public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array()) { return array( 'foo' => 'denormalizedFoo', diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php index 1b0516a417..e9db23882b 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php @@ -21,12 +21,12 @@ class ScalarDummy implements NormalizableInterface, DenormalizableInterface public $foo; public $xmlFoo; - public function normalize(NormalizerInterface $normalizer, $format = null) + public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array()) { return $format === 'xml' ? $this->xmlFoo : $this->foo; } - public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array()) { if ($format === 'xml') { $this->xmlFoo = $data;