Новое в Symfony 5.4: Улучшения сериализатора

Источник: «New in Symfony 5.4: Serializer improvements»
Symfony 5.4 вышел несколько дней назад, но у нас ещё есть записи в блоге об улучшениях основных функций ожидающие своей публикации. В этой публикации мы расскажем об улучшениях добавленных в компонент Serializer.

Глобально настроенный контекст сериализатора

Глобально настроенный контекст Сериализатора управляет (де) сериализацией ресурсов. В текущих версиях Symfony этот контекст передаётся всем нормализаторам. В Symfony 5.4 мы улучшаем конфигурацию компонента Serializer, чтобы вы могли настраивать контекст глобально, по умолчанию. Например:

# config/packages/serializer.yaml
serializer:
default_context:
enable_max_depth: true

В этом примере показана YAML конфигурация, но вы также может использовать конфигурационные файлы XML и PHP.

Пользовательский сериализатор для Symfony Messenger

Ожидается, что JSON-кодированные сообщения для Symfony Messenger, будут иметь следующую структуру:

{
"message": {
"body": {},
"headers": []
}
}

Однако, при использовании сообщений созданных различными третьими сторонами, вы не получите такую структуру сообщения. Вот почему в Symfony 5.4 вы можете использовать собственный сериализатор для JSON-декодирования сообщений.

Сбор ошибок Денормализированного типа

В предыдущих версиях сериализатора при использовании типизированных свойств PHP в определённых ситуациях можно было увидеть ошибки. Например, рассмотрим следующий простой DTO:

class MyDto
{
public string $property1;
public int $property2;
public array $property3;
}

Если ваши JSON данные выглядят следующим образом:

{
"property1": null,
"property2": 7,
"property3": []
}

При попытке десериализации этих данных вы увидите ошибку 500, потому что тип property1 - string, а вы передаёте null. В Symfony 5.4 мы улучшили это благодаря новой опции COLLECT_DENORMALIZATION_ERRORS.

Если вы передадите эту опцию, исключение PHP будет включать подробный список ошибок. Затем вы можете обработать его, как в следующем примере, который обрабатывает некий API:

#[Route('/api', methods:['POST'])]
public function apiPost(SerializerInterface $serializer, Request $request): Response
{
try {
$dto = $serializer->deserialize($request->getContent(), MyDto::class, 'json', [
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
]);
} catch (PartialDenormalizationException $e) {
$violations = new ConstraintViolationList();
/** @var NotNormalizableValueException */
foreach ($e->getErrors() as $exception) {
$message = sprintf('The type must be one of "%s" ("%s" given).', implode(', ', $exception->getExpectedTypes()), $exception->getCurrentType());
$parameters = [];
if ($exception->canUseMessageForUser()) {
$parameters['hint'] = $exception->getMessage();
}
$violations->add(new ConstraintViolation($message, '', $parameters, null, $exception->getPath(), null));
};

return $this->json($violations, 400);
}

return $this->json($dto);
}

Дополнительные материалы

Предыдущая Статья

Новое в Symfony 5.4: Улучшения профилиро­вщи­ка

Следующая Статья

Новое в Symfony 5.4: Различные улучшения (часть 1)