Symfony 2 使用自定义非规范化器对嵌套对象进行非规范化

Posted

技术标签:

【中文标题】Symfony 2 使用自定义非规范化器对嵌套对象进行非规范化【英文标题】:Symfony 2 denormalization of nested objects with custom denormalizers 【发布时间】:2017-05-02 00:03:38 【问题描述】:

Here 我正在为 REST API 构建 Symfony SDK。大多数数据是 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);

我正在使用我自己的自定义 Denormalizer,在 Tournament 对象的 denormalizer 代码片段下方:

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;
    

问题是我应该如何在 TournamentDenormalizer 中访问 TerritoryDe​​normalizer?我看到两个选项:

第一个(我现在正在使用)是将implements DenormalizerAwareInterface添加到非规范化器类的签名并依赖Symfony\Component\Serializer\Serializer类:

$serializer = new Symfony\Component\Serializer\Serializer(
    [
        new TournamentDenormalizer(),
        new TerritoryDenormalizer()
    ], [
        new Symfony\Component\Serializer\Encoder\JsonDecode()
    ]
);
$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)是可行的方法,这个接口已经针对这个特定的用例引入。

【讨论】:

以上是关于Symfony 2 使用自定义非规范化器对嵌套对象进行非规范化的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2:如何使用非默认实体管理器对用户进行身份验证?

为啥非规范化不返回嵌套对象?

在 Symfony 中将 JSON 转换为 Doctrine 实体

如何在 Handsontable 中使用自定义渲染器对列进行排序?

使用自定义分区器对 Pyspark 中的数据框进行分区

自定义嵌套表单类型 easyadmin