【问题标题】:Symfony+JMS Serializer deserialize into existing objectSymfony+JMS Serializer 反序列化为现有对象
【发布时间】:2018-08-31 11:52:12
【问题描述】:

我一直想知道是否可以使用 JMS 序列化器将 JSON 反序列化为现有对象。

通常这对于使用 JSON 格式的新数据更新现有对象很有用。 Symfony 的标准反序列化器似乎提供了这一点,但我似乎无法使用 JMS 找到任何关于此的信息。如果我想要 serializedName Annotation 选项,则必须使用 JMS。

“解决方法”是反序列化,然后使用 Doctrine 的 EntityManager 进行合并,但效果非常好,如果 JSON 不包含每个字段,您将无法轻松辨别哪些字段已更新。

【问题讨论】:

  • 在哪里可以看到标准的 Symfony 解串器提供的? JMS 只是一个更“完整”的序列化器,具有大量特性,但我怀疑它会缺乏与 Symfony 原生序列化器相比的特性
  • 我唯一知道这种情况发生的是当前会话中的用户,但反序列化的数据用于从数据库中获取用户,因此使用 Doctrine,因此不直接反序列化“进入”对象
  • 是的,似乎你可以用 JMS 做我想做的事,但在构建它时必须将一些东西放入上下文中,但还没有完全解决。

标签: symfony doctrine-orm jmsserializerbundle jms-serializer


【解决方案1】:

我一直在努力寻找解决方案,但终于找到了,我们开始吧:

  • 你的services.yaml
    jms_serializer.object_constructor:
        alias: jms_serializer.initialized_object_constructor

    jms_serializer.initialized_object_constructor:
        class: App\Service\InitializedObjectConstructor
        arguments: ["@jms_serializer.unserialize_object_constructor"]
  • 创建类App\Service\InitializedObjectConstructor.php
<?php

declare(strict_types=1);

namespace App\Service;

use JMS\Serializer\Construction\ObjectConstructorInterface;
use JMS\Serializer\DeserializationContext;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Visitor\DeserializationVisitorInterface;

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 deserialize 在升级到最新版本 (4.0) 后意外停止工作,只有您的解决方案有帮助。
【解决方案2】:

所以这是可以做到的,我还没有完全弄清楚如何做,但我再次离开了 JMS,所以仅供参考,因为我想这比无缘无故地保持开放要好:

https://github.com/schmittjoh/serializer/issues/79,您可能还会在 GitHub 上找到更多挖掘内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2013-06-20
    • 1970-01-01
    • 2018-04-26
    • 1970-01-01
    • 2017-08-28
    相关资源
    最近更新 更多