Symfony + JMS Serializer десериализует существующий объект

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

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

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

Где вы видите стандартный десериализатор Symfony, предлагающий такое? JMS - это всего лишь более "полный" сериализатор с тяжелыми функциями, но я сомневаюсь, что в нем не будет возможностей по сравнению с собственным сериализатором Symfony.

Florent Destremau 31.08.2018 16:47

Единственный раз, когда я знаю, что это происходит, это для пользователя в текущем сеансе, но десериализованные данные используются для выборки пользователя из базы данных, поэтому используется Doctrine, поэтому не выполняется прямая десериализация "в" объект

Florent Destremau 31.08.2018 16:49
symfony.com/doc/current/components/…
Inari 01.09.2018 17:18

И да, похоже, вы можете делать то, что я хочу, с JMS, имея необходимость помещать что-то в контекст, когда вы это создаете, хотя еще не полностью проработали это.

Inari 01.09.2018 19:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
1
4
1 995
2

Ответы 2

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

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

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

  • ваш 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);

Другие вопросы по теме