Как использовать (цепочку?) Несколько нормализаторов с Symfony Serializer?

Может кто-нибудь попытаться объяснить мне, как использовать несколько нормализаторов при сериализации данных из нескольких классов с помощью сериализатора Symfony?

Допустим, у меня есть следующие классы:

class User
{
    private $name;
    private $books;

    public function __construct()
    {
        $this->books = new ArrayCollection();
    }

    // getters and setters
}

class Book
{
    private $title;

    public function getTitle()
    {
        return $this->title;
    }    

    public function setTitle($title)
    {
        $this->title = $title;
    }
}

И я хочу сериализовать пользователя, у которого есть несколько книг.

$first = new Book();
$first->setTitle('First book');

$second = new Book();
$second->setTitle('Second book');

$user = new User();
$user->setName('Person name');
$user->addBook($first);
$user->addBook($second);

dump($this->get('serializer')->serialize($user, 'json'));
die();

Допустим, я также хочу включить хеш при сериализации книги, поэтому у меня есть следующий нормализатор:

class BookNormalizer implements NormalizerInterface
{
    public function normalize($object, $format = null, array $context = array())
    {
        return [
            'title' => $object->getTitle(),
            'hash' => md5($object->getTitle())
        ];
    }

    public function supportsNormalization($data, $format = null)
    {
        return $data instanceof Book;
    }
}

И я получаю ожидаемый результат:{"name":"Person name","books":[{"title":"First book","hash":"a9c04245e768bc5bedd57ebd62a6309e"},{"title":"Second book","hash":"c431a001cb16a82a937579a50ea12e51"}]}

Проблема возникает, когда я также добавляю нормализатор для класса User:

class UserNormalizer implements NormalizerInterface
{
    public function normalize($object, $format = null, array $context = array())
    {
        return [
            'name' => $object->getName(),
            'books' => $object->getBooks()
        ];
    }

    public function supportsNormalization($data, $format = null)
    {
        return $data instanceof User;
    }
}

Теперь книги не нормализованы с использованием ранее заданного нормализатора, и я получаю следующее:{"name":"Person name","books":[{},{}]}

Я попытался найти способ (документация и другие статьи), чтобы всегда вызывать нормализаторы для заданных типов (например, всегда вызывать нормализатор книги, когда тип является Book, даже если данные вложены и используются в другом нормализаторе), но не смог добиться успеха.

Я думаю, что неправильно понял нормализаторы, но не знаю что. Может кто-нибудь объяснить, что я хочу, и как это сделать?

1 ответ

Вы должны использовать NormalizerAwareTrait, чтобы получить доступ к нормализатору для книг.

  • добавить интерфейс
  • использовать черту
  • вызовите метод normalize() для книг

код:

class UserNormalizer implements NormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;

    public function normalize($object, $format = null, array $context = array())
    {
        return [
            'name' => $object->getName(),
            'books' => $this->normalizer->normalize($object->getBooks(), $format, $context)
        ];
    }

    public function supportsNormalization($data, $format = null)
    {
        return $data instanceof User;
    }
}
Другие вопросы по тегам