问题
This is my situation:
I'm trying to write a Symfony REST API that works with "strict" types (integer, boolean and float), because default Symfony behaviour doesn't support it and I want to avoid force cast types (e.g: JMS Serializer converts string value into integer field type)
To do this, I have created a custom handler which implements the JMS\Serializer\Handler\SubscribingHandlerInterface
(e.g a 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);
}
}
My entity looks:
<?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;
}
}
When I throw the following POST actions, the JMS Serializer returns the correct results:
{ "age" : 12 }
will result inint(12)
{ "age" : "asdf" }
will result in"Age field has wrong type"
In both cases my method deserializeStrictIntegerFromJSON
is called, so deserialize process works perfectly as I want.
Problems comes with serialize process:
When I launch GET action (/person/id_person
) I get the following exception:
Expected object but got integer. Do you have the wrong @Type mapping or could this be a Doctrine many-to-many relation? (JMS\Serializer\Exception\LogicException)
Debug stack trace shows me that method serializeStrictIntegerToJSON
is never called..
How can I solve it? Thanks.
回答1:
I have found the solution: I had to upgrade jms/serializer
library to version 1.5.0.
My problem was that I was using jms/serializer
(v1.1.0) whose SerializationContext
class was throwing the previous LogicException
in isVisiting()
method because strict_integer
type is not recognized in switch-case sentence from accept()
method of GraphNavigator
class.
来源:https://stackoverflow.com/questions/43868455/symfony-how-to-make-jms-serializer-works-with-strict-types