FOSRestBundle: partial response in the attribute function specified in the request

Context

I found a lot of questions about the partial API response with FOSRest, and all the answers are based on JMS serializer parameters (exception, inclusion, groups, etc.). It works fine, but I'm trying to achieve something less "static".

Say I have a user with the following attributes: id username firstname lastname age sex

I am extracting this user with the endpoint GET /users/{id} and in the following way:

 /** * @View * * GET /users/{id} * @param integer $user (uses ParamConverter) */ public function getUserAction(User $user) { return $user; } 

The method returns the user with all its attributes.

Now I want to allow something like this: GET /users/{id}?attributes=id,username,sex

Question

Did I miss the functionality of FOSRestBUndle, JMSserializer or SensioFrameworkExtraBundle to achieve this automatically? Annotations, method, keyword in a query, or something else?

Otherwise, what is the best way to achieve it?

The code

I thought of doing something like this:

 /** * @View * @QueryParam(name="attributes") * * GET /users/{id} * * @param integer $user (uses ParamConverter) */ public function getUserAction(User $user, $attributes) { $groups = $attributes ? explode(",", $attributes) : array("Default"); $view = $this->view($user, 200) ->setSerializationContext(SerializationContext::create()->setGroups($groups)); return $this->handleView($view); } 

And create a group for each attribute:

 use JMS\Serializer\Annotation\Groups; class User { /** @Groups({"id"}) */ protected $id; /** @Groups({"username"}) */ protected $username; /** @Groups({"firstname"}) */ protected $firstname; //etc } 
+5
source share
2 answers

You can do this as a group, as you have shown. Perhaps a more elegant solution would be to implement your own ExclusionStrategy . @Groups , and others are ExclusionStrategyInterface implementations too.

So, let's say you named your strategy SelectFieldsStrategy . After implementing it, you can easily add it to the serialization context:

 $context = new SerializationContext(); $context->addExclusionStrategy(new SelectFieldsStrategy(['id', 'name', 'someotherfield'])); 
+3
source

My implementation is based on Igor's Answer :

ExlusionStrategy:

 use JMS\Serializer\Exclusion\ExclusionStrategyInterface; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Context; class FieldsExclusionStrategy implements ExclusionStrategyInterface { private $fields = array(); public function __construct(array $fields) { $this->fields = $fields; } public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext) { return false; } public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext) { if (empty($this->fields)) { return false; } if (in_array($property->name, $this->fields)) { return false; } return true; } } 

Controller:

 /** * @View * @QueryParam(name="fields") * * GET /users/{id} * * @param integer $user (uses ParamConverter) */ public function getUserAction(User $user, $fields) { $context = new SerializationContext(); $context->addExclusionStrategy(new FieldsExclusionStrategy($fields ? explode(',', $fields) : array())); return $this->handleView($this->view($user)->setSerializationContext($context)); } 

End point:

 GET /users/{id}?fields=id,username,sex 
+4
source

Source: https://habr.com/ru/post/1208804/


All Articles