尝试在Symfony 3.3中使用序列化程序组件。我对拥有'DateTime'成员的实体感到困惑。
我的config.yml序列化程序init:
serializer:
enable_annotations: true
在service.yml中添加了这个:
datetime_method_normalizer:
class: Symfony\Component\Serializer\Normalizer\DateTimeNormalizer
public: false
tags: [serializer.normalizer]
反序列化的代码如下所示:
$yml = [...] // It was created by serializer->serialize()
$serializer = $this->get('serializer');
$myObject = $serializer->deserialize($yml, MyObject::class, "yaml");
错误是get:Expected argument of type "DateTime", "string" given
in in vendor / symfony / symfony / src / Symfony / Component / Serializer / Normalizer / AbstractObjectNormalizer.php(第204行)
我认为DateTimeNormalizer :: denormalize永远不会被调用。知道如何让它恢复生机吗?
Info:调用DateTimeNormalizer :: __ constructor()。
答案 0 :(得分:2)
这个问题最近打破了我的大脑,我有两个带有dateTime属性的实体,解决方案是这样的自定义非规范化器:
<?php
namespace MyBundle\Serializer\Normalizer;
use MyBundle\Entity\MyEntity1;
use MyBundle\Entity\MyEntity2;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
/**
* DateTime hook normalizer
*/
class DateTimeHookNormalizer implements DenormalizerInterface
{
/**
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = null, array $context = array())
{
if (isset($data['MyDateTime1']) && is_string($data['MyDateTime1']))
{
$data['MyDateTime1'] = new \DateTime($data['MyDateTime1']);
}
if (isset($data['MyDateTime2']) && is_string($data['MyDateTime2']))
{
$data['MyDateTime2'] = new \DateTime($data['MyDateTime2']);
}
And more ...
$normalizer = new ObjectNormalizer();//default normalizer
return $normalizer->denormalize($data, $class, $format, $context);
}
}
/**
* {@inheritdoc}
*/
public function supportsDenormalization($data, $type, $format = null)
{
return is_array($data) && ($type === MyEntity1::class || $type === MyEntity2::class);
}
并宣布这样的服务:
# DateTime Hook Normalizer
Mybundle.normalizer.dateTimeHook:
class: 'MybundleBundle\Serializer\Normalizer\DateTimeHookNormalizer'
public: false
tags: [serializer.normalizer]
对我来说没关系,那工作!
答案 1 :(得分:2)
由于DateTime是一个嵌套对象,因此您应按此处所述使用PropertyInfo Component — https://symfony.com/doc/current/components/serializer.html#recursive-denormalization-and-type-safety
属性信息的提取由提取器执行 课程。
https://symfony.com/doc/current/components/property_info.html#extractors
有4种类型的提取器:
例如,使用ReflectionExtractor,您需要为参数或返回类型指定类型提示。它还会寻找构造函数参数(需要显式启用)
class Item {
protected $date;
public function setDate(\DateTime $date) {...}
public function getDate() : \DateTime {...}
}
在设置选项时自动注册属性信息:
# config/packages/framework.yaml
framework:
property_info: ~
此后,您需要覆盖 serializer 服务以使用它,或定义一个自定义服务。最后一部分-添加DateTimeNormalizer,以便序列化程序可以处理DateTime。
app.normalizer.item_normalizer:
class: Symfony\Component\Serializer\Normalizer\ObjectNormalizer
arguments:
- null
- null
- null
- '@property_info.reflection_extractor'
tags: [ 'serializer.normalizer' ]
app.serializer.item:
class: Symfony\Component\Serializer\Serializer
public: true
arguments:
- [
'@serializer.normalizer.datetime',
'@app.normalizer.item_normalizer',
]
- [ '@serializer.encoder.json' ]
就是这样。
答案 2 :(得分:0)
唯一的官方方式似乎是宣布callback
:
$callback = function ($dateTime) {
return $dateTime instanceof \DateTime
? $dateTime->format(\DateTime::ISO8601)
: '';
};
$normalizer->setCallbacks(array('createdAt' => $callback));
$serializer = new Serializer(array($normalizer), array($encoder));