Мне было интересно, можно ли использовать сериализатор JMS для десериализации JSON в существующий объект.
Обычно это бывает полезно для обновления существующего объекта новыми данными, которые у вас есть в формате JSON. Стандартный десериализатор Symfony, кажется, предлагает это, но я не могу найти ничего об этом с JMS. Придется использовать JMS, если мне нужна опция аннотации serializedName.
«Обходной путь» - десериализовать, а затем использовать EntityManager Doctrine для слияния, но это работает очень хорошо, и вы не можете легко определить, какие поля обновляются, если JSON не содержит все поля.
Единственный раз, когда я знаю, что это происходит, это для пользователя в текущем сеансе, но десериализованные данные используются для выборки пользователя из базы данных, поэтому используется Doctrine, поэтому не выполняется прямая десериализация "в" объект
И да, похоже, вы можете делать то, что я хочу, с JMS, имея необходимость помещать что-то в контекст, когда вы это создаете, хотя еще не полностью проработали это.




Так что это можно сделать, я не совсем понял, как, но я снова отказался от 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);
Где вы видите стандартный десериализатор Symfony, предлагающий такое? JMS - это всего лишь более "полный" сериализатор с тяжелыми функциями, но я сомневаюсь, что в нем не будет возможностей по сравнению с собственным сериализатором Symfony.