Это моя ситуация:
Я пытаюсь написать API-интерфейс Symfony REST, который работает со «строгими» типами (целочисленными, логическими и с плавающей точкой), потому что поведение Symfony по умолчанию не поддерживает его, и я хочу избежать принудительного приведения типов (например: Сериализатор JMS преобразует строковое значение в тип целочисленного поля)
Для этого я создал собственный обработчик, который реализует 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
тип не распознается в предложении о переключении accept()
метод GraphNavigator
учебный класс.
Это моя ситуация:
Я пытаюсь написать API-интерфейс Symfony REST, который работает со «строгими» типами (целочисленными, логическими и с плавающей точкой), потому что поведение Symfony по умолчанию не поддерживает его, и я хочу избежать принудительного приведения типов (например: Сериализатор JMS преобразует строковое значение в тип целочисленного поля)
Для этого я создал собственный обработчик, который реализует 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
тип не распознается в предложении о переключении accept()
метод GraphNavigator
учебный класс.