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

здесь Я создаю Symfony SDK для REST API. Большинство данных-это объекты JSON с вложенными другими объектами JSON. Как здесь

{
    "id": "eng_pl",
    "name": "Premier League",
    "_links": {
        "self": {
            "href": "/tournaments/eng_pl"
        },
        "seasons": {
            "href": "/tournaments/eng_pl/seasons/"
        }
    },
    "coverage": {
        "id": "eng",
        "name": "England",
        "_links": {
            "self": {
                "href": "/territories/eng"
            }
        }
    }
}

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

$tournament = new Tournament();
$tournament->setId('eng_pl');
$tournament->setName('Premier League');

$coverage = new Territory();
$coverage->setId('eng');
$coverage->setName('England');

$tournament->setCoverage($coverage);

Я использую свои собственные Денормализаторы, ниже фрагмента кода денормализатора для объектов турнира:

class TournamentDenormalizer implements DenormalizerInterface
{

    /**
     * @inheritdoc
     */
    public function supportsDenormalization($object, $type, $format = null)
    {

        if ($type != Tournament::class) {
            return false;
        }
        return true;
    }

    /**
     * @inheritdoc
     * @return Tournament
     */
    public function denormalize($object, $class, $format = null, array $context = array())
    {
        $tournament = new Tournament();
        $tournament->setId($object->id);
        $tournament->setName($object->name);

        if (isset($object->coverage)) {
            /** @var Territory $coverage */
            $coverage = ???; //HOWTO how to implement Territory denormalization here???
            $tournament->setCoverage(
                $coverage
            );
        }
            return $tournament;
    }
}

вопрос в том, как я должен получить доступ к TerritoryDenormalizer внутри TournamentDenormalizer? Я вижу два варианта:

первый (я использую сейчас), чтобы добавить implements DenormalizerAwareInterface подписи класса denormalizer и положиться на SymfonyComponentSerializerSerializer класс:

$serializer = new SymfonyComponentSerializerSerializer(
    [
        new TournamentDenormalizer(),
        new TerritoryDenormalizer()
    ], [
        new SymfonyComponentSerializerEncoderJsonDecode()
    ]
);
$serializer->deserialize($json, Tournament::class, 'json');

так TournamentDeserializer это будет как здесь:

if (isset($object->coverage)) {
        /** @var Territory $coverage */
        $coverage = $this->denormalizer->denormalize(
            $object->coverage,
            Territory::class,
            $format,
            $context
        );
        $tournament->setCoverage(
            $coverage
        );
    }
}

второй подход Это ввести необходимые денормализаторы явно

$tournamentDenormalizer = new TournamentDenormalizer();
$tournamentDenormalizer->setTerritoryDenormalizer(new TerritoryDenormalizer());

так TournamentDeserializer это будет как здесь:

if (isset($object->coverage)) {
        /** @var Territory $coverage */
        $coverage = $this->territoryDenormalizer->denormalize(
            $object->coverage,
            Territory::class,
            $format,
            $context
        );
        $tournament->setCoverage(
            $coverage
        );
    }
}

какой из подходов лучше? Какие альтернативные подходы возможны?

1 ответов


сделать ваш нормализатор реализовать NormalizerAwareInterface (и в конечном итоге использовать NormalizerAwareTrait) - это путь, этот интерфейс был введен для этого конкретного случая использования.