How do I create a custom exclusion strategy for JMS Serializer that allows me to make run-time decisions about whether to include a particular field?

后端 未结 2 1707
小蘑菇
小蘑菇 2020-12-31 19:42

As the title says, I am trying to make a run-time decision on whether or not to include fields in the serialization. In my case, this decision will be based on permissions.<

相关标签:
2条回答
  • 2020-12-31 20:17

    You just have to create a class that implements JMS\Serializer\Exclusion\ExclusionStrategyInterface

    <?php
    
    namespace JMS\Serializer\Exclusion;
    
    use JMS\Serializer\Metadata\ClassMetadata;
    use JMS\Serializer\Metadata\PropertyMetadata;
    use JMS\Serializer\Context;
    
    interface ExclusionStrategyInterface
    {
        /**
         * Whether the class should be skipped.
         *
         * @param ClassMetadata $metadata
         *
         * @return boolean
         */
        public function shouldSkipClass(ClassMetadata $metadata, Context $context);
    
        /**
         * Whether the property should be skipped.
         *
         * @param PropertyMetadata $property
         *
         * @return boolean
         */
        public function shouldSkipProperty(PropertyMetadata $property, Context $context);
    }
    

    In your case, you can implement your own custom logic in the shouldSkipProperty method and always return false for shouldSkipClass.

    Example of implementation can be found in the JMS/Serializer repository

    We will reference the created service as acme.my_exclusion_strategy_service below.


    In your controller action:

    <?php
    
    use Symfony\Component\HttpFoundation\Response;
    use JMS\Serializer\SerializationContext;
    
    // ....
    
    $context = SerializationContext::create()
        ->addExclusionStrategy($this->get('acme.my_exclusion_strategy_service'));
    
    $serial = $this->get('jms_serializer')->serialize($object, 'json', $context);
    
    return new Response($serial, Response::HTTP_OK, array('Content-Type' => 'application/json'));
    

    Or if you are using FOSRestBundle

    <?php
    
    use FOS\RestBundle\View;
    use JMS\Serializer\SerializationContext;
    
    // ....
    
    $context = SerializationContext::create()
        ->addExclusionStrategy($this->get('acme.my_exclusion_strategy_service'))
    
    $view = new View($object);
    $view->setSerializationContext($context);
    
    // or you can create your own view factory that handles the creation
    // of the context for you
    
    return $this->get('fos_rest.view_handler')->handle($view);
    
    0 讨论(0)
  • 2020-12-31 20:30

    As of jms/serializer 1.4.0, the symfony expression language is integrated in its core.

    The feature is documented at http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies#dynamic-exclusion-strategy and this allows to use runtime exclusion strategies.

    An example taken from the documentation is:

    class MyObject
    {
        /**
         * @Exclude(if="service('user_manager_service').getSomeRuntimeData(object)")
         */
        private $name;
    
       /**
         * @Expose(if="service('request_stack').getCurrent().has('foo')")
         */
        private $name2;
    }
    

    I this example, the services user_manager_service and request_stack are invoked at runtime, and depending on the return (true or false), the property will be exposed or not.

    With the same expression language, as of 1.6.0 is possible also to use virtual properties via expression language. Documented at http://jmsyst.com/libs/serializer/master/reference/annotations#virtualproperty allows to add on the fly data coming from external services

    0 讨论(0)
提交回复
热议问题