Skip to content

Serializer Encoders

Edit this page

The Serializer component provides several built-in encoders:

JsonEncoder
This class encodes and decodes data in JSON.
XmlEncoder
This class encodes and decodes data in XML.
YamlEncoder
This encoder encodes and decodes data in YAML. This encoder requires the Yaml Component.
CsvEncoder
This encoder encodes and decodes data in CSV.

Note

You can also create your own encoder to use another structure. Read more at Creating a Custom Encoder below.

All these encoders are enabled by default when using the Serializer component in a Symfony application.

The JsonEncoder

The JsonEncoder encodes to and decodes from JSON strings, based on the PHP json_encode and json_decode functions.

It can be useful to modify how these functions operate in certain instances by providing options such as JSON_PRESERVE_ZERO_FRACTION. You can use the serialization context to pass in these options using the key json_encode_options or json_decode_options respectively:

1
2
3
$this->serializer->serialize($data, 'json', [
    'json_encode_options' => \JSON_PRESERVE_ZERO_FRACTION,
]);

All context options available for the JSON encoder are:

json_decode_associative (default: false)
If set to true returns the result as an array, returns a nested stdClass hierarchy otherwise.
json_decode_detailed_errors (default: false)
If set to true exceptions thrown on parsing of JSON are more specific. Requires seld/jsonlint package.
json_decode_options (default: 0)
Flags passed to json_decode function.
json_encode_options (default: \JSON_PRESERVE_ZERO_FRACTION)
Flags passed to json_encode function.
json_decode_recursion_depth (default: 512)
Sets maximum recursion depth.

The CsvEncoder

The CsvEncoder encodes to and decodes from CSV. Serveral context options are available to customize the behavior of the encoder:

csv_delimiter (default: ,)
Sets the field delimiter separating values (one character only).
csv_enclosure (default: ")
Sets the field enclosure (one character only).
csv_end_of_line (default: \n)
Sets the character(s) used to mark the end of each line in the CSV file.

csv_escape_char (default: empty string)

7.2

The csv_escape_char option was deprecated in Symfony 7.2.

Sets the escape character (at most one character).

csv_key_separator (default: .)
Sets the separator for array's keys during its flattening
csv_headers (default: [], inferred from input data's keys)
Sets the order of the header and data columns. E.g. if you set it to ['a', 'b', 'c'] and serialize ['c' => 3, 'a' => 1, 'b' => 2], the order will be a,b,c instead of the input order (c,a,b).
csv_escape_formulas (default: false)
Escapes fields containing formulas by prepending them with a \t character.
as_collection (default: true)
Always returns results as a collection, even if only one line is decoded.
no_headers (default: false)
Setting to false will use first row as headers when denormalizing, true generates numeric headers.
output_utf8_bom (default: false)
Outputs special UTF-8 BOM along with encoded data.

The XmlEncoder

This encoder transforms PHP values into XML and vice versa.

For example, take an object that is normalized as following:

1
$normalizedArray = ['foo' => [1, 2], 'bar' => true];

The XmlEncoder will encode this object like:

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8" ?>
<response>
    <foo>1</foo>
    <foo>2</foo>
    <bar>1</bar>
</response>

The special # key can be used to define the data of a node:

1
2
3
4
5
6
7
8
9
10
['foo' => ['@bar' => 'value', '#' => 'baz']];

/* is encoded as follows:
   <?xml version="1.0"?>
   <response>
       <foo bar="value">
          baz
       </foo>
   </response>
 */

Furthermore, keys beginning with @ will be considered attributes, and the key #comment can be used for encoding XML comments:

1
2
3
4
5
6
7
8
9
10
11
12
$encoder = new XmlEncoder();
$xml = $encoder->encode([
    'foo' => ['@bar' => 'value'],
    'qux' => ['#comment' => 'A comment'],
], 'xml');
/* will return:
   <?xml version="1.0"?>
   <response>
       <foo bar="value"/>
       <qux><!-- A comment --!><qux>
   </response>
 */

You can pass the context key as_collection in order to have the results always as a collection.

Note

You may need to add some attributes on the root node:

1
2
3
4
5
6
7
8
9
10
11
12
$encoder = new XmlEncoder();
$encoder->encode([
    '@attribute1' => 'foo',
    '@attribute2' => 'bar',
    '#' => ['foo' => ['@bar' => 'value', '#' => 'baz']]
], 'xml');

// will return:
// <?xml version="1.0"?>
// <response attribute1="foo" attribute2="bar">
// <foo bar="value">baz</foo>
// </response>

Tip

XML comments are ignored by default when decoding contents, but this behavior can be changed with the optional context key XmlEncoder::DECODER_IGNORED_NODE_TYPES.

Data with #comment keys are encoded to XML comments by default. This can be changed by adding the \XML_COMMENT_NODE option to the XmlEncoder::ENCODER_IGNORED_NODE_TYPES key of the $defaultContext of the XmlEncoder constructor or directly to the $context argument of the encode() method:

1
$xmlEncoder->encode($array, 'xml', [XmlEncoder::ENCODER_IGNORED_NODE_TYPES => [\XML_COMMENT_NODE]]);

The XmlEncoder Context Options

These are the options available on the serializer context:

xml_format_output (default: false)
If set to true, formats the generated XML with line breaks and indentation.
xml_version (default: 1.0)
Sets the XML version attribute.
xml_encoding (default: utf-8)
Sets the XML encoding attribute.
xml_standalone (default: true)
Adds standalone attribute in the generated XML.
xml_type_cast_attributes (default: true)
This provides the ability to forget the attribute type casting.
xml_root_node_name (default: response)
Sets the root node name.
as_collection (default: false)
Always returns results as a collection, even if only one line is decoded.
decoder_ignored_node_types (default: [\XML_PI_NODE, \XML_COMMENT_NODE])
Array of node types (DOM XML_* constants) to be ignored while decoding.
encoder_ignored_node_types (default: [])
Array of node types (DOM XML_* constants) to be ignored while encoding.
load_options (default: \LIBXML_NONET | \LIBXML_NOBLANKS)
XML loading options with libxml.
save_options (default: 0)
XML saving options with libxml.
remove_empty_tags (default: false)
If set to true, removes all empty tags in the generated XML.
cdata_wrapping (default: true)
If set to false, will not wrap any value containing one of the following characters ( <, >, &) in a CDATA section like following: <![CDATA[...]]>.
cdata_wrapping_pattern (default: ``/[<>&]/``)
A regular expression pattern to determine if a value should be wrapped in a CDATA section.

7.1

The cdata_wrapping_pattern option was introduced in Symfony 7.1.

Example with a custom context:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use Symfony\Component\Serializer\Encoder\XmlEncoder;

$data = [
    'id' => 'IDHNQIItNyQ',
    'date' => '2019-10-24',
];

$xmlEncoder->encode($data, 'xml', ['xml_format_output' => true]);
// outputs:
// <?xml version="1.0"?>
// <response>
//   <id>IDHNQIItNyQ</id>
//   <date>2019-10-24</date>
// </response>

$xmlEncoder->encode($data, 'xml', [
    'xml_format_output' => true,
    'xml_root_node_name' => 'track',
    'encoder_ignored_node_types' => [
        \XML_PI_NODE, // removes XML declaration (the leading xml tag)
    ],
]);
// outputs:
// <track>
//   <id>IDHNQIItNyQ</id>
//   <date>2019-10-24</date>
// </track>

The YamlEncoder

This encoder requires the Yaml Component and transforms from and to Yaml.

Like other encoder, several context options are available:

yaml_inline (default: 0)
The level where you switch to inline YAML.
yaml_indent (default: 0)
The level of indentation (used internally).
yaml_flags (default: 0)
A bit field of Yaml::DUMP_*/Yaml::PARSE_* constants to customize the encoding/decoding YAML string.

Creating a Custom Encoder

Imagine you want to serialize and deserialize NEON. For that you'll have to create your own encoder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// src/Serializer/YamlEncoder.php
namespace App\Serializer;

use Nette\Neon\Neon;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;

class NeonEncoder implements EncoderInterface, DecoderInterface
{
    public function encode($data, string $format, array $context = [])
    {
        return Neon::encode($data);
    }

    public function supportsEncoding(string $format)
    {
        return 'neon' === $format;
    }

    public function decode(string $data, string $format, array $context = [])
    {
        return Neon::decode($data);
    }

    public function supportsDecoding(string $format)
    {
        return 'neon' === $format;
    }
}

Tip

If you need access to $context in your supportsDecoding or supportsEncoding method, make sure to implement Symfony\Component\Serializer\Encoder\ContextAwareDecoderInterface or Symfony\Component\Serializer\Encoder\ContextAwareEncoderInterface accordingly.

Registering it in Your App

If you use the Symfony Framework, then you probably want to register this encoder as a service in your app. If you're using the default services.yaml configuration, that's done automatically!

If you're not using autoconfigure, make sure to register your class as a service and tag it with serializer.encoder:

1
2
3
4
5
6
# config/services.yaml
services:
    # ...

    App\Serializer\NeonEncoder:
        tags: ['serializer.encoder']

Now you'll be able to serialize and deserialize NEON!

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version