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.
I am using Symfony 2, so what I'm looking to do is add an additional annotation called @ExcludeIf which accepts a security expression.
I can handle the annotation parsing and storing of the meta data, but I am not able to see how to integrate a custom exclusion strategy with the library.
Any suggestions?
Note: exclusion strategies are an actual construct in the JMS codebase, I just haven't been able to figure out the best way to integrate an extra on top of the others
PS: I had asked about this before and was pointed to using groups. For various reasons this is a very poor solution for my needs.
The serializer supports different exclusion strategies. Each strategy allows you to define which properties of your objects should be serialized. If you would like to always expose, or exclude certain properties.
Note: exclusion strategies are an actual construct in the JMS codebase, I just haven't been able to figure out the best way to integrate an extra on top of the others PS: I had asked about this before and was pointed to using groups. For various reasons this is a very poor solution for my needs. Show activity on this post.
Another default exclusion strategy is to create different views of your objects. Let?s say you would like to serialize your object in a different view depending whether it is displayed in a list view or in a details view.
Each strategy allows you to define which properties of your objects should be serialized. If you would like to always expose, or exclude certain properties. Then, you can do this with the annotations @ExclusionPolicy, @Exclude, and @Expose.
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);
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With