我正在尝试编写一个REST API,它在Symfony2中使用来自PUT请求的JSON。将JSON反序列化为实体类型 - 但是如果JSON中的属性类型与实体的相应属性不匹配,JMS Serializer似乎强制来自JSON的类型而不是抛出异常。
例如......
{ "id" : "123" }
...将导致......
int(123)
...如果属性id
被定义为实体中的整数。
但我希望JMS Serializer能够抛出异常。有谁知道如何实现这个目标?
我发现JMS Serializer的类型处理的一个问题是:
{ "id" : "n123" }
将导致......
int(0)
完全不受欢迎。
有人可以指出我正确的方向吗?
答案 0 :(得分:6)
getting help over at Github之后我想就自己的问题分享答案。
解决方案的关键是使用实现JMS\Serializer\Handler\SubscribingHandlerInterface
的自定义处理程序(例如StrictIntegerHandler
)。
<?php
namespace MyBundle\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);
}
}
然后,您需要将序列化程序定义为服务:
services:
mybundle.serializer.strictinteger:
class: MyBundle\Serializer\StrictIntegerHandler
tags:
- { name: jms_serializer.subscribing_handler }
然后您就可以使用strict_integer
类型:
MyBundle\Entity\MyEntity:
exclusion_policy: ALL
properties:
id:
expose: true
type: strict_integer
在控制器中反序列化然后照常工作。
奖励:现在使用类型验证器终于有意义了:
MyBundle\Entity\MyEntity:
properties:
id:
- Type:
type: integer
message: id {{ value }} is not an integer.
我希望这可以帮助那些有同样问题的人。
答案 1 :(得分:3)
建立在reieRMeister的答案之上,当谈到JSON反序列化时,我认为默认情况下强制原始类型是不明智的。
当需要在“严格”和“宽松”类型之间进行区分时,通过为每个属性明确设置类型strict_integer
,reieRMaster的答案很好。但是,如果您希望使用内置功能(使用原则元数据确定类型),这会变得有些繁琐。
您可以通过使用您自己的类之一覆盖jms_serializer.json_deserialization_visitor.class
来覆盖所有基元类型的默认行为,如下所示:
<?php
namespace MyBundle\Serializer\Visitor;
use JMS\Serializer\JsonDeserializationVisitor;
use JMS\Serializer\Context;
class JsonNativeDeserializationVisitor extends JsonDeserializationVisitor
{
public function visitString($data, array $type, Context $context)
{
return $data;
}
public function visitBoolean($data, array $type, Context $context)
{
return $data;
}
public function visitInteger($data, array $type, Context $context)
{
return $data;
}
public function visitDouble($data, array $type, Context $context)
{
return $data;
}
}
并在services.xml(或services.yml)中覆盖jms_serializer.json_deserialization_visitor.class
<parameters>
<parameter key="jms_serializer.json_deserialization_visitor.class">MyBundle\Serializer\Visitor\JsonNativeDeserializationVisitor</parameter>
</parameters>
<强>疑难杂症!强> 确保您的软件包已注册 AFTER JMSSerializer软件包,否则上述操作无效。 How to do that is described here