Это моя ситуация:
Я пытаюсь написать API-интерфейс Symfony REST, который работает со строгими типами (integer, boolean и float), потому что поведение по умолчанию Symfony не поддерживает его, и я хочу избежать типов принудительного применения (например: JMS Serializer преобразует строковое значение в тип целочисленного поля )
Для этого я создал пользовательский обработчик, который реализует JMS\Serializer\Handler\SubscribingHandlerInterface
(например, StrictIntegerHandler
):
<?php namespace AppBundle\Serializer; use JMS\Serializer\Context; use JMS\Serializer\GraphNavigator; use JMS\Serializer\Handler\SubscribingHandlerInterface; use JMS\Serializer\JsonDeserializationVisitor; use JMS\Serializer\JsonSerializationVisitor; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; class StrictIntegerHandler implements SubscribingHandlerInterface { public static function getSubscribingMethods() { return [ [ 'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, 'format' => 'json', 'type' => 'strict_integer', 'method' => 'deserializeStrictIntegerFromJSON', ], [ 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'format' => 'json', 'type' => 'strict_integer', 'method' => 'serializeStrictIntegerToJSON', ], ]; } public function deserializeStrictIntegerFromJSON( JsonDeserializationVisitor $visitor, $data, array $type) { return $data; } public function serializeStrictIntegerToJSON( JsonSerializationVisitor $visitor, $data, array $type, Context $context) { return $visitor->visitInteger($data, $type, $context); } }
Моя сущность выглядит:
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Validator; /** * Person * * @ORM\Table(name="persons") * @ORM\Entity(repositoryClass="AppBundle\Repository\PersonRepository") */ class Person { /** * @var int age * * @ORM\Column(name="age", type="integer") * * @Serializer\Type("strict_integer") * @Serializer\Groups({"Person"}) * * @Validator\Type(type="integer", message="Age field has wrong type") */ private $age; public function getAge() { return $this->age; } public function setAge(int $age) { $this->age = $age; } }
Когда я бросаю следующие действия POST, JMS Serializer возвращает правильные результаты:
{ "age" : 12 }
приведет к int(12)
{ "age" : "asdf" }
приведет к тому, что "Age field has wrong type"
В обоих случаях мой метод deserializeStrictIntegerFromJSON
вызывается, поэтому процесс десериализации работает отлично, как я хочу.
Проблемы возникают с процессом сериализации: когда я запускаю действие GET ( /person/id_person
), я получаю следующее исключение:
Ожидаемый объект, но получил целое число. У вас неправильное сопоставление @Type, или это может быть отношение Доктрина «многие ко многим»? (JMS \ Serializer \ Exception \ LogicException)
Трассировка стека отладки показывает мне, что метод serializeStrictIntegerToJSON
никогда не вызывается ..
Как я могу это решить? Благодарю.
Я нашел решение: мне пришлось обновить библиотеку jms/serializer
до версии 1.5.0.
Моя проблема заключалась в том, что я использовал jms/serializer
(v1.1.0), класс SerializationContext
которого выкидывал предыдущий LogicException
в isVisiting()
потому strict_integer
тип strict_integer
не распознается в предложении switch-case метода accept()
класса GraphNavigator
.