如何使 JMS 序列化程序在反序列化 JSON 而不是强制类型时抛出异常?
How to make JMS Serializer throw an exception on deserializing JSON instead of coercing types?
我正在尝试编写一个 REST API,它使用来自 Symfony2 中 PUT 请求的 JSON。将 JSON 反序列化为实体类型的作品——但 JMS 序列化器似乎从 JSON 强制类型,而不是在 [=37= 中的 属性 类型时抛出异常]不匹配实体对应的属性.
例如……
{ "id" : "123" }
… 将导致…
int(123)
…如果属性 id
在实体中定义为整数。
但我希望 JMS 序列化程序改为抛出异常。有谁知道如何做到这一点?
更新2016-02-27
我发现 JMS 序列化程序类型处理的一个问题是:
{ "id" : "n123" }
将导致……
int(0)
这是完全不受欢迎的。
有人能给我指出正确的方向吗?
在 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.
希望对遇到同样问题的人有所帮助。
基于 reieRMeister 的回答,当谈到 JSON 反序列化时,我认为默认强制原始类型是不明智的。
当需要通过将每个 属性 的类型显式设置为 strict_integer
来区分 "strict" 和 "loose" 类型时,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
我正在尝试编写一个 REST API,它使用来自 Symfony2 中 PUT 请求的 JSON。将 JSON 反序列化为实体类型的作品——但 JMS 序列化器似乎从 JSON 强制类型,而不是在 [=37= 中的 属性 类型时抛出异常]不匹配实体对应的属性.
例如……
{ "id" : "123" }
… 将导致…
int(123)
…如果属性 id
在实体中定义为整数。
但我希望 JMS 序列化程序改为抛出异常。有谁知道如何做到这一点?
更新2016-02-27
我发现 JMS 序列化程序类型处理的一个问题是:
{ "id" : "n123" }
将导致……
int(0)
这是完全不受欢迎的。
有人能给我指出正确的方向吗?
在 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.
希望对遇到同样问题的人有所帮助。
基于 reieRMeister 的回答,当谈到 JSON 反序列化时,我认为默认强制原始类型是不明智的。
当需要通过将每个 属性 的类型显式设置为strict_integer
来区分 "strict" 和 "loose" 类型时,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