diff --git a/components/index.rst b/components/index.rst index 780b33b2c9e..c165dce5b01 100644 --- a/components/index.rst +++ b/components/index.rst @@ -25,7 +25,7 @@ The Components property_access/index routing/index security/index - serializer + serializer/index stopwatch templating/index translation/index diff --git a/components/map.rst.inc b/components/map.rst.inc index b69b347373f..1a7c811bdfe 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -1,7 +1,7 @@ * :doc:`/components/using_components` * :doc:`/components/browser_kit/index` - + * :doc:`/components/browser_kit/introduction` * :doc:`/components/class_loader/index` @@ -121,9 +121,11 @@ * :doc:`/components/security/authorization` * :doc:`/components/security/secure_tools` -* **Serializer** +* :doc:`/components/serializer/index` - * :doc:`/components/serializer` + * :doc:`/components/serializer/introduction` + * :doc:`/components/serializer/encoders` + * :doc:`/components/serializer/normalizers` * **Stopwatch** diff --git a/components/serializer/encoders.rst b/components/serializer/encoders.rst new file mode 100644 index 00000000000..8df13b97bd2 --- /dev/null +++ b/components/serializer/encoders.rst @@ -0,0 +1,105 @@ +.. index:: + single: Serializer, Encoders + +Encoders +======== + +Encoders basically turn **arrays** into **formats** and vice versa. +They implement :class:`Symfony\\Component\\Serializer\\Encoder\\EncoderInterface` for encoding (array to format) and :class:`Symfony\\Component\\Serializer\\Encoder\\DecoderInterface` for decoding (format to array). + +You can add new encoders to a Serializer instance by using its second constructor argument:: + + use Symfony\Component\Serializer\Serializer; + use Symfony\Component\Serializer\Encoder\XmlEncoder; + use Symfony\Component\Serializer\Encoder\JsonEncoder; + + $encoders = array(new XmlEncoder(), new JsonEncoder()); + $serializer = new Serializer(array(), $encoders); + +Built-in encoders +----------------- + +You can see in the example above that we use two encoders: + +* :class:`Symfony\\Component\\Serializer\\Encoder\\XmlEncoder` to encode/decode XML +* :class:`Symfony\\Component\\Serializer\\Encoder\\JsonEncoder` to encode/decode JSON + +The ``XmlEncoder`` +~~~~~~~~~~~~~~~~~~ + +This encoder transform arrays into XML and vice versa. + +For example, we will guess that you have an object normalized as following:: + + array('foo' => array(1, 2), 'bar' => true); + +The ``XmlEncoder`` will encode this object like that:: + + + + 1 + 2 + 1 + + +Be aware that this encoder will consider keys beginning with ``@`` as attributes:: + + $encoder = new XmlEncoder(); + $encoder->encode(array('foo' => array('@bar' => 'value'))); + // will return: + // + // + // + // + +The ``JsonEncoder`` +~~~~~~~~~~~~~~~~~~~ + +The ``JsonEncoder`` is much simpler and is based on the PHP `json_encode`_ and `json_decode`_ functions. + +.. _json_encode: https://secure.php.net/manual/fr/function.json-encode.php +.. _json_decode: https://secure.php.net/manual/fr/function.json-decode.php + +Custom encoders +--------------- + +If you need to support another format than XML and JSON, you can create your own encoder. +We will guess that you want to serialize and deserialize Yaml. For that, we will use +:doc:`/components/yaml/index`:: + + namespace App\Encoder; + + use Symfony\Component\Serializer\Encoder\DecoderInterface; + use Symfony\Component\Serializer\Encoder\EncoderInterface; + use Symfony\Component\Yaml\Yaml; + + class YamlEncoder implements EncoderInterface, DecoderInterface + { + public function encode($data, $format, array $context = array()) + { + return Yaml::dump($data); + } + + public function supportsEncoding($format) + { + return 'json' === $format; + } + + public function decode($data, $format, array $context = array()) + { + return Yaml::parse($data); + } + + public function supportsDecoding($format) + { + return 'json' === $format; + } + } + +Then just pass it to your serializer:: + + use Symfony\Component\Serializer\Serializer; + + $serializer = new Serializer(array(), array(new App\Encoder\YamlEncoder())); + +Now you'll be able to serialize and deserialize Yaml. diff --git a/components/serializer/index.rst b/components/serializer/index.rst new file mode 100644 index 00000000000..f79113aed18 --- /dev/null +++ b/components/serializer/index.rst @@ -0,0 +1,9 @@ +Serializer +========== + +.. toctree:: + :maxdepth: 2 + + introduction + encoders + normalizers diff --git a/components/serializer.rst b/components/serializer/introduction.rst similarity index 55% rename from components/serializer.rst rename to components/serializer/introduction.rst index 9d1d80df053..a95aaf987e0 100644 --- a/components/serializer.rst +++ b/components/serializer/introduction.rst @@ -47,11 +47,20 @@ which Encoders and Normalizer are going to be available:: use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; + // Allows to serialize/deserialize in JSON and XML $encoders = array(new XmlEncoder(), new JsonEncoder()); + // Allows to normalize objects thanks to their getters and setters $normalizers = array(new GetSetMethodNormalizer()); $serializer = new Serializer($normalizers, $encoders); +The following examples assume that you instantiate the serializer as above. + +.. note:: + + Read the dedicated sections to learn more about :doc:`/components/serializer/encoders` + and :doc:`/components/serializer/normalizers`. + Serializing an Object --------------------- @@ -105,29 +114,6 @@ The first parameter of the :method:`Symfony\\Component\\Serializer\\Serializer:: is the object to be serialized and the second is used to choose the proper encoder, in this case :class:`Symfony\\Component\\Serializer\\Encoder\\JsonEncoder`. -Ignoring Attributes when Serializing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 2.3 - The :method:`GetSetMethodNormalizer::setIgnoredAttributes` - method was introduced in Symfony 2.3. - -As an option, there's a way to ignore attributes from the origin object when -serializing. To remove those attributes use the -:method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setIgnoredAttributes` -method on the normalizer definition:: - - use Symfony\Component\Serializer\Serializer; - use Symfony\Component\Serializer\Encoder\JsonEncoder; - use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; - - $normalizer = new GetSetMethodNormalizer(); - $normalizer->setIgnoredAttributes(array('age')); - $encoder = new JsonEncoder(); - - $serializer = new Serializer(array($normalizer), array($encoder)); - $serializer->serialize($person, 'json'); // Output: {"name":"foo"} - Deserializing an Object ----------------------- @@ -141,6 +127,7 @@ of the ``Person`` class would be encoded in XML format:: EOF; + // Will return an instance of Acme\Person $person = $serializer->deserialize($data, 'Acme\Person', 'xml'); In this case, :method:`Symfony\\Component\\Serializer\\Serializer::deserialize` @@ -150,69 +137,11 @@ needs three parameters: #. The name of the class this information will be decoded to #. The encoder used to convert that information into an array -Using Camelized Method Names for Underscored Attributes -------------------------------------------------------- - -.. versionadded:: 2.3 - The :method:`GetSetMethodNormalizer::setCamelizedAttributes` - method was introduced in Symfony 2.3. - -Sometimes property names from the serialized content are underscored (e.g. -``first_name``). Normally, these attributes will use get/set methods like -``getFirst_name``, when ``getFirstName`` method is what you really want. To -change that behavior use the -:method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setCamelizedAttributes` -method on the normalizer definition:: - - $encoder = new JsonEncoder(); - $normalizer = new GetSetMethodNormalizer(); - $normalizer->setCamelizedAttributes(array('first_name')); - - $serializer = new Serializer(array($normalizer), array($encoder)); - - $json = <<deserialize($json, 'Acme\Person', 'json'); - -As a final result, the deserializer uses the ``first_name`` attribute as if -it were ``firstName`` and uses the ``getFirstName`` and ``setFirstName`` methods. - -Using Callbacks to Serialize Properties with Object Instances -------------------------------------------------------------- - -When serializing, you can set a callback to format a specific object property:: - - use Acme\Person; - use Symfony\Component\Serializer\Encoder\JsonEncoder; - use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; - use Symfony\Component\Serializer\Serializer; - - $encoder = new JsonEncoder(); - $normalizer = new GetSetMethodNormalizer(); - - $callback = function ($dateTime) { - return $dateTime instanceof \DateTime - ? $dateTime->format(\DateTime::ISO8601) - : ''; - }; - - $normalizer->setCallbacks(array('createdAt' => $callback)); - - $serializer = new Serializer(array($normalizer), array($encoder)); - - $person = new Person(); - $person->setName('cordoval'); - $person->setAge(34); - $person->setCreatedAt(new \DateTime('now')); +Go further +---------- - $serializer->serialize($person, 'json'); - // Output: {"name":"cordoval", "age": 34, "createdAt": "2014-03-22T09:43:12-0500"} +If this is not already done, you should take a look at :doc:`/components/serializer/encoders` +and :doc:`/components/serializer/normalizers` to be able to use the entire abilities of this component. JMSSerializer ------------- diff --git a/components/serializer/normalizers.rst b/components/serializer/normalizers.rst new file mode 100644 index 00000000000..1b349c8e778 --- /dev/null +++ b/components/serializer/normalizers.rst @@ -0,0 +1,23 @@ +.. index:: + single: Security, Normalizers + +Normalizers +=========== + +Normalizers turn **objects** into **arrays** and vice-versa. +They implement :class:`Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface` for normalizing (object to array) and :class:`Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface` for denormalizing (array to object). + +You can add new normalizers to a Serializer instance by using its first constructor argument:: + + use Symfony\Component\Serializer\Serializer; + use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; + use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; + + $normalizers = array(new ArrayDenormalizer(), new GetSetMethodNormalizer()); + $serializer = new Serializer($normalizers); + +Built-in encoders +----------------- + +The Serializer Component provides several normalizers for most use cases: + * diff --git a/cookbook/serializer.rst b/cookbook/serializer.rst index eedaf349fc6..4b9f4a0b256 100644 --- a/cookbook/serializer.rst +++ b/cookbook/serializer.rst @@ -6,11 +6,11 @@ How to Use the Serializer Serializing and deserializing to and from objects and different formats (e.g. JSON or XML) is a very complex topic. Symfony comes with a -:doc:`Serializer Component`, which gives you some +:doc:`Serializer Component`, which gives you some tools that you can leverage for your solution. In fact, before you start, get familiar with the serializer, normalizers -and encoders by reading the :doc:`Serializer Component`. +and encoders by reading the :doc:`Serializer Component`. You should also check out the `JMSSerializerBundle`_, which expands on the functionality offered by Symfony's core serializer. diff --git a/redirection_map b/redirection_map index 6e8ea5d953f..76cbe33826c 100644 --- a/redirection_map +++ b/redirection_map @@ -24,6 +24,7 @@ /components/routing /components/routing/introduction /cookbook/console/generating_urls /cookbook/console/sending_emails /components/yaml /components/yaml/introduction +/components/serializer /components/serializer/introduction /components/templating /components/templating/introduction /cookbook/upgrading /cookbook/upgrade/index /cookbook/security/voters_data_permission /cookbook/security/voters