Як використовувати Serializer

Дата оновлення перекладу 2024-06-10

Як використовувати 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 буде доступний у контейнері. Він постачається з набором корисних кодувальників та нормалізаторів .

Включені кодувальники, які підтримують наступні формати:

А також наступні нормалізатори:

Інші вбудовані нормалізатори та користувацькі нормалізатори та/або кодувальники також можна завантажити, тегувавши їх як serializer.normalizer та serializer.encoder . Також можливо встановити пріоритет тегу для того, щоб вирішити порядок співствалення.

Danger

Не забувайте завантажувати DateTimeNormalizer при серіалізації класів DateTime або DateTimeImmutable для уникнення надмірного використання пам'яті та розголошення внутрішніх деталей.

Контекст Serializer

Serializer може визначати контекст для контролю (де)серіалізації джерел. Цей контекст передається всім нормалізаторам. Наприклад:

  • DateTimeNormalizer використовує ключ datetime_format у форматі дати та часу;
  • AbstractObjectNormalizer uses preserve_empty_objects to represent empty objects as {} instead of [] in JSON.
  • Serializer uses empty_array_as_object to represent empty arrays as {} instead of [] in 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;

    // ...
}

Використайте опції, щоб вказати контекст конкретно для нормалізації або денормалізації:

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;

    // ...
}

Атрибут може повторюватися в одній властивості стільки разів, скільки потрібно. Контекст без групи завжди застосовується першим. Потім контекст для груп, що співпали, зливається у наданому порядку.

Якщо ви повторюєте один і той самий контекст у декількох властивостях, розгляньте можливість використання атрибуту #[Контекст] у вашому класі, щоб застосувати цю конфігурацію контексту до до всіх властивостей класу:

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;
}

Ви також можете використовувати атрибут #[Groups] на рівні класу:

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-систему, яка підтримує наступні формати:

Вона вбудована над фреймворком Symfony та її компонентом Serializer. Вона надає користувацькі нормалізатори та кодувальники, користувацькі метадані та систему кешування.

Якщо ви хочете скористатися перевагами повної потужності компонента Symfony Serializer, подвіться на те, як працює цей пакет.