Status Badges (for master)
, (*1)
JLMSerializerExpression
This library adds expression language support to Johannes Schmitt's Serializer library so that individual fields can be hidden based on expressions at runtime via an @excludeIf
annotation., (*2)
Installation
This library can be included via Composer by adding the following to your composer.json
file:, (*3)
"require": {
# ..
"jlm/serializer-expression": "dev-master"
# ..
}
Usage
The library provides an exclusion strategy that must be configured and then added to your serialization context. Using this serialization context, when you serialize an object it is inspected for @excludeIf
annotations which are then processed at runtime., (*4)
The exclusion strategy has two dependencies, an instance of JMS\Metadata\MetadataFactory
from Johannes Schmitt's Metadata library and an instance of Symfony\Component\ExpressionLanguage\ExpressionLanguage
which must be extended to provide the functionality you need., (*5)
Annotating Your Objects
The @excludeIf
annotation accepts an expression that must be processable by the ExpressionLanguage
instance you pass to the exclusion strategy. In the example below, we are using a dummy hasAccessIfTrue
expression function that is created in the Creating the Expression Language section below. It isn't very useful, naturally. Creating a useful expression language is application-specific and left up to you. To see an example for Symfony applications, check out the Symfony bundle of this library., (*6)
<?php
use JLM\SerializerExpression\Annotation\ExcludeIf;
class User
{
/**
* @ExcludeIf("hasAccessIfTrue(true)")
*/
public $firstName = 'Jason';
/**
* @ExcludeIf("hasAccessIfTrue(true)")
*/
public $lastName = 'McClellan';
/**
* @ExcludeIf("hasAccessIfTrue(false)")
*/
public $phone = '555-555-5555';
/**
* @ExcludeIf("hasAccessIfTrue(false)")
*/
public $address ='New York, NY';
public $occupation = 'Software';
}
Given the above annotations, I would expect that if this object were serialized with a SerializationContext
that included the ExpressionBasedExclusionStrategy
configured with our custom ExpressionLanguage
, we would only see 3 fields in the serialized output:
- first_name
- last_name
- occupation, (*7)
The metadata factory is what lets us store the expressions from our annotations. As such, it requires that we provide it with a way to read our @excludeIf
annotation. The library comes with a built-in metadata driver with annotation capabilities: JLM\SerializerExpression\Metadata\Driver\AnnotationDriver
which can be used directly, but it needs to be provided with an annotation reader. We are using Doctrine\Common\Annotations\AnnotationReader
from the Doctrine Common Library., (*8)
use Doctrine\Common\Annotations\AnnotationReader;
use JLM\SerializerExpression\Metadata\Driver\AnnotationDriver;
use JMS\Metadata\MetadataFactory;
$annotationReader = new AnnotationReader();
$annotationDriver = new AnnotationDriver($annotationReader);
$metadataFactory = new MetadataFactory($annotationDriver);
To improve performance, it is strongly suggested that you enable caching for the metadata factory. File-based caching can be achieved as such:, (*9)
use Metadata\Cache\FileCache;
$metadataCache = new FileFache('/path/to/cache/dir');
$metadataFactory->setCache($metadataCache);
Creating the Expression Language
The expression language is out of scope for this documentation. For that, please see the relevant Symfony documentation., (*10)
However, here is a quick (and useless) example:, (*11)
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
class CustomExpressionLanguage extends BaseExpressionLanguage
{
protected function registerFunctions()
{
parent::registerFunctions();
// Test expression which always returns the opposite of the value we pass to it
$this->register('hasAccessIfTrue', function ($arg) {
return sprintf('return !%s', $arg);
}, function (array $variables, $value) {
return !$value;
});
}
}
Full Example
use JMS\Metadata\MetadataFactory;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\SerializationContext;
use Doctrine\Common\Annotations\AnnotationReader;
use JLM\SerializerExpression\Metadata\Driver\AnnotationDriver;
$expressionLang = new CustomExpressionLanguage();
$metadataDriver = new AnnotationDriver($annotationReader);
$metadataFactory = new MetadataFactory($metadataDriver);
$exclusionStrategy = new ExpressionBasedExclusionStrategy($metadataFactory, $expressionLang);
$serializationContext = SerializationContext::create();
$serializationContext->addExclusionStrategy($exclusionStrategy);
$serializer = SerializerBuilder::create()->build();
$serializedContent = $serializer->serialize($data, 'json', $serializationContext);