How to create a custom exclusion strategy for JMS Serializer that allows me to make decisions while working on whether to include a specific field?

As the title says, I'm trying to make a decision in time about including fields in serialization. In my case, this solution will be based on permissions.

I am using Symfony 2, so I want to add an additional annotation called @ExcludeIf that accepts a security expression.

I can handle parsing annotations and saving metadata, but I cannot figure out how to integrate a custom exception strategy with the library.

Any suggestions?

Note: exclusion strategies are an actual construct in the JMS code base, I just could not find a better way to integrate additional information on top of others.

PS: I asked about this before and pointed out the use of groups. For various reasons, this is a very bad solution for my needs.

+7
symfony jmsserializerbundle jms-serializer
source share
2 answers

You just need 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 logic in the shouldSkipProperty method and always return false for shouldSkipClass .

An example implementation can be found in the JMS / Serializer repository.

We refer to the created service as acme.my_exclusion_strategy_service below.


In the action of your controller:

 <?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 use 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); 
+10
source share

According to jms/serializer 1.4.0, the symfony expression language is integrated into its core.

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

Example from the documentation:

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

In this example, the user_manager_service and request_stack services user_manager_service called at run time, and depending on the return ( true or false ), the property will be open or not.

With the same expression language, starting with version 1.6.0, you can also use virtual properties through the expression language. Documented at http://jmsyst.com/libs/serializer/master/reference/annotations#virtualproperty allows you to add data on the fly from external services

+2
source share

All Articles