Как использовать Serializer
Дата обновления перевода 2024-08-01
Как использовать Serializer
Symfony предоставляет Serializer для сериализации/десериализации в и из объектов и разных форматов (например, JSON или XML). До его использования, прочтите документы компонента Serializer, который предоставляет вам некоторые инструменты, которые вы можете использовать для решения ваших задач.
Установка
В приложениях, использующих Symfony Flex , выполните эту команду,
чтобы установить пакет Symfony serializer
перед его использованием:
1
$ composer require symfony/serializer-pack
Использование сервиса Serializer
После подключения, сервис сериализатора может быть внедрен в любой сервис, где вам это нужно, или он может быть использован в контроллере:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/Controller/DefaultController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\SerializerInterface;
class DefaultController extends AbstractController
{
public function index(SerializerInterface $serializer): Response
{
// продолжайте читать для примеров использования
}
}
Или вы можете использовать фильтр Twig serialize
в шаблоне:
1
{{ object|serialize(format = 'json') }}
См. справочник twig, чтобы узнать больше информации.
Добавление нормализаторов и кодировшиков
После подключения, сервис serializer
будет доступен в контейнере.
Он поставляется с набором полезных кодировщиков
и нормализаторов .
Включены кодировщики, поддерживающие следующие форматы:
- JSON: JsonEncoder
- XML: XmlEncoder
- CSV: CsvEncoder
- YAML: YamlEncoder
А также следующие нормализаторы:
- ObjectNormalizer
- DateTimeNormalizer
- DateTimeZoneNormalizer
- DateIntervalNormalizer
- FormErrorNormalizer
- DataUriNormalizer
- JsonSerializableNormalizer
- ArrayDenormalizer
- ConstraintViolationListNormalizer
- ProblemNormalizer
- BackedEnumNormalizer
- TranslatableNormalizer
Другие встроенные нормализаторы и пользовательские нормализаторы и/или кодировщики также могут быть загружены, путем тегирования их как serializer.normalizer и serializer.encoder . Также возможно установить приоритет тега, чтобы опрределить порядок сопоставления.
Danger
Не забывайте загружать DateTimeNormalizer
при сериализации классов
DateTime
или DateTimeImmutable
для избежания излишнего использования
памяти и оголения внутренних деталей.
Контекст сериализатора
Сериализатор может определять контекст для контроля (де)сериализацию источников. Этот контекст передается всем нормализаторам. К примеру:
- DateTimeNormalizer использует
ключ
datetime_format
в формате даты и времени; - AbstractObjectNormalizer
использует
empty_iterable_as_object
, чтобы представлять пустые объекты как{}
вместо[]
в JSON. - Serializer использует
empty_array_as_object
для представления пустых массивов как{}
вместо[]
в JSON.
Вы можете передать контекст следующим образом:
1 2 3 4 5 6 7
$serializer->serialize($something, 'json', [
DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i:s',
]);
$serializer->deserialize($someJson, Something::class, 'json', [
DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i:s',
]);
Вы также можете сконфигурироовать контекст по умолчанию через конфигурацию фреймворка:
1 2 3 4 5 6 7
# config/packages/framework.yaml
framework:
# ...
serializer:
default_context:
enable_max_depth: true
yaml_indentation: 2
Вы также можете указать контекст в зависимости от свойства:
1 2 3 4 5 6 7 8 9 10 11 12
namespace App\Model;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Person
{
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
public \DateTimeInterface $createdAt;
// ...
}
Use the options to specify context specific to normalization or denormalization:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
namespace App\Model;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Person
{
#[Context(
normalizationContext: [DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'],
denormalizationContext: [DateTimeNormalizer::FORMAT_KEY => '!Y-m-d'], // To prevent to have the time from the moment of denormalization
)]
public \DateTimeInterface $createdAt;
// ...
}
Вы также можете ограничить использование контекста по каким-то группам:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
namespace App\Model;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Person
{
#[Groups(['extended'])]
#[Context([DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339])]
#[Context(
context: [DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339_EXTENDED],
groups: ['extended'],
)]
public \DateTimeInterface $createdAt;
// ...
}
Атрибут может повторяться необходимое количество раз в одном свойстве. Контекст без группы всегда применяется первым. Затем, контекст для совпадающих групп слияется в предоставленном порядке.
Если вы повторяете один и тот же контекст в нескольких свойствах,
подумайте об использовании атрибута #[Context]
в вашем классе, чтобы применить конфигурацию контекста ко
всем свойствам класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
namespace App\Model;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
#[Context([DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339])]
#[Context(
context: [DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339_EXTENDED],
groups: ['extended'],
)]
class Person
{
// ...
}
Использование конструкторов контекста
Чтобы определить контекст (де)сериализации, вы можете использовать "конструкторы контекста", которые являются объектами, помогающими вам создавать этот контекст, предоставляя автозаполнение, валидацию и документацию:
1 2 3 4
use Symfony\Component\Serializer\Context\Normalizer\DateTimeNormalizerContextBuilder;
$contextBuilder = (new DateTimeNormalizerContextBuilder())->withFormat('Y-m-d H:i:s');
$serializer->serialize($something, 'json', $contextBuilder->toArray());
Каждый нормализатор/кодировщик имеет связанный с ним конструктор контекста .
Чтобы создать более сложный контекст (де)сериализации, вы можете цепочку,
используя метод withContext()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use Symfony\Component\Serializer\Context\Encoder\CsvEncoderContextBuilder;
use Symfony\Component\Serializer\Context\Normalizer\ObjectNormalizerContextBuilder;
$initialContext = [
'custom_key' => 'custom_value',
];
$contextBuilder = (new ObjectNormalizerContextBuilder())
->withContext($initialContext)
->withGroups(['group1', 'group2']);
$contextBuilder = (new CsvEncoderContextBuilder())
->withContext($contextBuilder)
->withDelimiter(';');
$serializer->serialize($something, 'csv', $contextBuilder->toArray());
Вы также можете создавать собственные конструкторы контекста, чтобы иметь автозаполнение, валидацию и документацию для ваших пользовательских значений контекста.
Использование атрибутов групповой сериализации
Вы можете добавить атрибуты #[Groups] к вашему классу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// src/Entity/Product.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
#[ORM\Entity]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(['show_product', 'list_product'])]
private int $id;
#[ORM\Column(type: 'string', length: 255)]
#[Groups(['show_product', 'list_product'])]
private string $name;
#[ORM\Column(type: 'text')]
#[Groups(['show_product'])]
private string $description;
}
You can also use the #[Groups]
attribute on class level:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#[ORM\Entity]
#[Groups(['show_product'])]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(['list_product'])]
private int $id;
#[ORM\Column(type: 'string', length: 255)]
#[Groups(['list_product'])]
private string $name;
#[ORM\Column(type: 'text')]
private string $description;
}
В этом примере свойства id
и name
принадлежат к группам show_product
и list_product
. Свойство description
принадлежит только к группе show_product
.
Теперь, когда группы определены, вы можете выбрать, какие группы использовать при сериализации:
1 2 3 4 5 6 7
use Symfony\Component\Serializer\Context\Normalizer\ObjectNormalizerContextBuilder;
$context = (new ObjectNormalizerContextBuilder())
->withGroups('show_product')
->toArray();
$json = $serializer->serialize($product, 'json', $context);
Tip
Значение ключа groups
может быть одной строкой или их массивом.
В дополенение к атрибуту #[Groups]
, компонент Serializer также поддерживает
файлы YAML или XML. Эти файлы автоматически загружаются при сохранении в одной
из следующих локаций:
- Все файлы
*.yaml
и*.xml
в каталогеconfig/serializer/
. - Файл
serialization.yaml
илиserialization.xml
в каталоге пакетаResources/config/
; - Все файлы
*.yaml
и*.xml
в каталоге пакетаResources/config/serialization/
.
Note
По умолчанию при нормализации и денормализации объектов используются группы Default
и группа, соответствующая имени класса. Например, если вы
нормализуете объект App\Entity\Product
, то будут использоваться группы
Default
и Product
.
7.1
- Использование имени класса и группы
Default
по умолчанию при нормализации - и денормализации объектов было представлено в Symfony 7.1.
Использование вложенных атрибутов
Чтобы отобразить вложенные свойства, используйте конфигурацию SerializedPath
, чтобы
определить их пути, используя валидный синтаксис PropertyAccess:
1 2 3 4 5 6 7 8 9 10 11
namespace App\Model;
use Symfony\Component\Serializer\Annotation\SerializedPath;
class Person
{
#[SerializedPath('[profile][information][birthday]')]
private string $birthday;
// ...
}
Используя конфигурацию выше, денормализация с нормализатором, знающим о метаданных,
впишет поле birthday
из $data
в объект Person
:
1 2 3 4 5 6 7 8 9
$data = [
'profile' => [
'information' => [
'birthday' => '01-01-1970',
],
],
];
$person = $normalizer->denormalize($data, Person::class, 'any');
$person->getBirthday(); // 01-01-1970
При использовании аннотаций или атрибутов, SerializedPath
может либо быть
установлен в свойстве, либо в ассоциированном методе _getter_. SerializedPath
не может быть использован в комбинации с SerializedName
для одного свойства.
Конфигурация кеша метаданных
Метаданные для сериализатора автоматически кешируются для улучшения работы
приложения. По умолчанию, сериализатор использует пул кеша cache.system
,
который конфигурируется с использованием опции cache.system .
Подключения конвертера имен
Использование сервиса конвертера имен может быть определено в конфигурации с использованием опции name_converter .
Встроенный конвертер имен CamelCase в snake_case
может быть подключен, используя значение serializer.name_converter.camel_case_to_snake_case
:
1 2 3 4 5
# config/packages/framework.yaml
framework:
# ...
serializer:
name_converter: 'serializer.name_converter.camel_case_to_snake_case'
Отладка Serializer
Используйте команду debug:serializer
, чтобы сбросить метаданные сериализатора
заданного класса:
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 30 31 32
$ php bin/console debug:serializer 'App\Entity\Book'
App\Entity\Book
---------------
+----------+------------------------------------------------------------+
| Свойство | Опции |
+----------+------------------------------------------------------------+
| name | [ |
| | "groups" => [ |
| | "book:read", |
| | "book:write", |
| | ], |
| | "maxDepth" => 1, |
| | "serializedName" => "book_name", |
| | "serializedPath" => null, |
| | "ignore" => false, |
| | "normalizationContexts" => [], |
| | "denormalizationContexts" => [] |
| | ] |
| isbn | [ |
| | "groups" => [ |
| | "book:read", |
| | ], |
| | "maxDepth" => null, |
| | "serializedName" => null, |
| | "serializedPath" => [data][isbn], |
| | "ignore" => false, |
| | "normalizationContexts" => [], |
| | "denormalizationContexts" => [] |
| | ] |
+----------+------------------------------------------------------------+
Углублённое использование Serializer
Платформа API предоставляет API-систему, поддерживающую следующие форматы:
- JSON-LD вместе со словарем Hydra Core
- OpenAPI v2 (ранее Swagger) и v3
- GraphQL
- JSON:API
- HAL
- JSON
- XML
- YAML
- CSV
Она встроена над фреймворком Symfony и ее компонентом Serializer. Она предоставляет пользовательские нормализаторы и кодировщики, пользовательсские метаданные и систему кеширования.
Если вы хотите воспользоваться преимуществами полной мощи компонента Symfony Serializer, посмотрите на то, как работает этот пакет.