Как использовать Serializer

Дата обновления перевода 2023-01-11

Как использовать 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
// src/Controller/DefaultController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Serializer\SerializerInterface;

class DefaultController extends AbstractController
{
    public function index(SerializerInterface $serializer)
    {
        // продолжайте читать для примеров использования
    }
}

Или вы можете использовать фильтр Twig serialize в шаблоне:

1
{{ object|serialize(format = 'json') }}

См. справочник twig, чтобы узнать больше информации.

Добавление нормализаторов и кодировшиков

После подключения, сервис serializer будет доступен в контейнере. Он поставляется с набором полезных кодировщиков и нормализаторов .

Включены кодировщики, поддерживающие следующие форматы:

А также следующие нормализаторы:

Другие встроенные нормализаторы и пользовательские нормализаторы и/или кодировщики также могут быть загружены, путем тегирования их как serializer.normalizer и serializer.encoder . Также возможно установить приоритет тега, чтобы опрределить порядок сопоставления.

Caution

Не забывайте загружать 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',
]);

Вы также можете сконфигурироовать контекст по умолчанию через конфигурацию фреймворка:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
# config/packages/framework.yaml
framework:
    # ...
    serializer:
        default_context:
            enable_max_depth: true
            yaml_indentation: 2

6.2

Опция конфигурации отступа YAML была представлена в Symfony 6.2.

Вы также можете указать контекст в зависимости от свойства:

  • Annotations
  • Attributes
  • YAML
  • XML
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;

class Person
{
    /**
     * @Context({ DateTimeNormalizer::FORMAT_KEY = 'Y-m-d' })
     */
    public $createdAt;

    // ...
}

Используйте опции, чтобы указать контекст, относящийся к нормализации или денормализации:

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 => \DateTime::RFC3339],
    )]
    public $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 $createdAt;

    // ...
}

Атрибут/аннотация могут повторяться необходимое количество раз в одном свойстве. Контекст без группы всегда применяется первым. Затем, контекст для совпадающих групп слияется в предоставленном порядке.

Использование конструкторов контекста

6.1

Конструкторы контекста были представлены в Symfony 6.1.

Чтобы определить контекст (де)сериализации, вы можете использовать "конструкторы контекста", которые являются объектами, помогающими вам создавать этот контекст, предоставляя автозаполнение, валидацию и документацию:

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 $id;

    #[ORM\Column(type: 'string', length: 255)]
    #[Groups(['show_product', 'list_product'])]
    private $name;

    #[ORM\Column(type: 'integer')]
    #[Groups(['show_product'])]
    private $description;
}

Теперь вы можете выбрать, какие группы использовать при сериализации:

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/.

Использование вложенных атрибутов

Чтобы отобразить вложенные свойства, используйте конфигурацию SerializedPath, чтобы определить их пути, используя валидный синтаксис PropertyAccess:

  • Annotations
  • Attributes
  • YAML
  • XML
1
2
3
4
5
6
7
8
9
10
11
12
13
namespace App\Model;

use Symfony\Component\Serializer\Annotation\SerializedPath;

class Person
{
    /**
     * @SerializedPath("[profile][information][birthday]")
     */
    private string $birthday;

    // ...
}

6.2

Опция конфигурирования SerializedPath была представлена в Symfony 6.2.

Используя конфигурацию выше, денормализация с нормализатором, знающим о метаданных, впишет поле 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:

  • YAML
  • XML
  • PHP
1
2
3
4
5
# config/packages/framework.yaml
framework:
    # ...
    serializer:
        name_converter: 'serializer.name_converter.camel_case_to_snake_case'

Углубленное использование Serializer

Платформа API предоставляет API-систему, поддерживающую следующие форматы:

Она встроена над фреймворком Symfony и ее компонентом Serializer. Она предоставляет пользовательские нормализаторы и кодировщики, пользовательсские метаданные и систему кеширования.

Если вы хотите воспользоваться преимуществами полной мощи компонента Symfony Serializer, посмотрите на то, как работает этот пакет.