代码之家  ›  专栏  ›  技术社区  ›  reieRMeister

如何使JMS序列化程序在反序列化JSON而不是强制类型时抛出异常?

  •  6
  • reieRMeister  · 技术社区  · 10 年前

    我正在尝试编写一个REST API,它从Symfony2中的PUT请求中使用JSON。将JSON反序列化为一个实体有点管用,但如果JSON中的属性类型与实体的相应属性不匹配,JMS序列化程序似乎会从JSON中强制类型,而不是抛出异常。

    例如

    { "id" : "123" }
    

    将导致

    int(123)
    

    如果属性 id 在实体中定义为整数。

    但我希望JMS序列化程序抛出一个异常。有人知道如何做到这一点吗?

    更新2016-02-27

    我发现JMS序列化程序类型处理的一个问题是:

    { "id" : "n123" }
    

    将导致

    int(0)
    

    这是完全不希望的。

    有人能告诉我正确的方向吗?

    2 回复  |  直到 10 年前
        1
  •  6
  •   reieRMeister    10 年前

    之后 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.
    

    我希望这能帮助那些有同样问题的人。

        2
  •  3
  •   Community Mohan Dere    9 年前

    基于reieRMeister的回答,当谈到JSON反序列化时,我认为在默认情况下强制原始类型是不明智的。

    当需要通过将类型显式设置为 strict_integer 每个属性。但是,如果您希望使用内置特性(其中类型是使用条令元数据确定的),这会变得有些乏味。

    您可以通过重写 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;
        }
    
    }
    

    以及在服务中。xml(或services.yml)覆盖 jms_serializar.json_derialization_visitor.class

    <parameters>
        <parameter key="jms_serializer.json_deserialization_visitor.class">MyBundle\Serializer\Visitor\JsonNativeDeserializationVisitor</parameter>
    </parameters>
    

    明白了! 确保您的捆绑包已注册 之后 JMSSerializer bundle,或以上版本将不起作用。 How to do that is described here

    推荐文章