Symfony + JMS Serializer десериализуется в существующий объект - PullRequest
0 голосов
/ 31 августа 2018

Мне было интересно, можно ли использовать сериализатор JMS для десериализации JSON в существующий объект.

Обычно это будет полезно для обновления существующего объекта новыми данными, имеющимися в формате JSON. Стандартный десериализатор Symfony, кажется, предлагает это, но я не могу найти ничего об этом с JMS. Должен использовать JMS, хотя, если я хочу вариант serializedName Annotation.

«Обходной путь» заключается в десериализации и последующем использовании EntityManager Doctrine для слияния, но это работает только так хорошо, и вы не можете легко определить, какие поля обновляются, если JSON не содержит каждое отдельное поле.

Ответы [ 2 ]

0 голосов
/ 14 мая 2019

Я изо всех сил пытался найти решение, но, наконец, нашел его, и вот мы:

  • ваш 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);
0 голосов
/ 16 сентября 2018

Так что это можно сделать, я не до конца понял, как, но я снова переключился с JMS, просто для справки, так как, я думаю, это лучше, чем держать вопрос открытым без причины:

https://github.com/schmittjoh/serializer/issues/79 и вы можете найти больше копаний вокруг GitHub.

...