Serializer Encoders
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 nestedstdClass
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)- 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 bea,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
or Symfony
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!