我一直想知道是否可以使用 JMS 序列化程序将 JSON 反序列化为现有对象。
通常,这对于使用JSON格式的新数据更新现有对象很有用。Symfony的标准反序列化器似乎提供了这一点,但我似乎在JMS上找不到任何关于这一点的东西。如果我想要序列化名称注释选项,则必须使用 JMS。
"解决方法"是反序列化,然后使用Doctrine的EntityManager进行合并,但这只能很好地工作,如果JSON不包含每个字段,则无法轻松识别哪些字段已更新。
我一直在努力寻找解决方案,但最终找到了它,我们开始了:
- 您的
services.yaml
jms_serializer.object_constructor:
alias: jms_serializer.initialized_object_constructor
jms_serializer.initialized_object_constructor:
class: AppServiceInitializedObjectConstructor
arguments: ["@jms_serializer.unserialize_object_constructor"]
- 创建类
AppServiceInitializedObjectConstructor.php
<?php
declare(strict_types=1);
namespace AppService;
use JMSSerializerConstructionObjectConstructorInterface;
use JMSSerializerDeserializationContext;
use JMSSerializerMetadataClassMetadata;
use JMSSerializerVisitorDeserializationVisitorInterface;
class InitializedObjectConstructor implements ObjectConstructorInterface
{
private $fallbackConstructor;
/**
* @param ObjectConstructorInterface $fallbackConstructor Fallback object constructor
*/
public function __construct(ObjectConstructorInterface $fallbackConstructor)
{
$this->fallbackConstructor = $fallbackConstructor;
}
/**
* {@inheritdoc}
*/
public function construct(
DeserializationVisitorInterface $visitor,
ClassMetadata $metadata,
$data,
array $type,
DeserializationContext $context
): ?object {
if ($context->hasAttribute('target') && 1 === $context->getDepth()) {
return $context->getAttribute('target');
}
return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type, $context);
}
}
- 在您的控制器或服务文件中
$object = $this->entityManager->find('YourEntityName', $id);
$context = new DeserializationContext();
$context->setAttribute('target', $object);
$data = $this->serializer->deserialize($request->getContent(), 'YourEntityClassName', 'json', $context);
所以这是可以做到的,我还没有完全弄清楚如何做,但我再次从 JMS 切换,所以仅供参考,因为我想这比无缘无故地保持问题开放要好:
https://github.com/schmittjoh/serializer/issues/79,你可能会在GitHub周围找到更多的挖掘。