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 中访问 TerritoryDenormalizer?我看到两个选项:
第一个(我现在正在使用)是将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 实体