exclusion_strategies.rst 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. Exclusion Strategies
  2. ====================
  3. Introduction
  4. ------------
  5. The serializer supports different exclusion strategies. Each strategy allows
  6. you to define which properties of your objects should be serialized.
  7. General Exclusion Strategies
  8. ----------------------------
  9. If you would like to always expose, or exclude certain properties. Then, you can
  10. do this with the annotations ``@ExclusionPolicy``, ``@Exclude``, and ``@Expose``.
  11. The default exclusion policy is to exclude nothing. That is, all properties of the
  12. object will be serialized. If you only want to expose a few of the properties,
  13. then it is easier to change the exclusion policy, and only mark these few properties:
  14. .. code-block :: php
  15. <?php
  16. use JMS\Serializer\Annotation\ExclusionPolicy;
  17. use JMS\Serializer\Annotation\Expose;
  18. /**
  19. * The following annotations tells the serializer to skip all properties which
  20. * have not marked with @Expose.
  21. *
  22. * @ExclusionPolicy("all")
  23. */
  24. class MyObject
  25. {
  26. private $foo;
  27. private $bar;
  28. /**
  29. * @Expose
  30. */
  31. private $name;
  32. }
  33. .. note ::
  34. A property that is excluded by ``@Exclude`` cannot be exposed anymore by any
  35. of the following strategies, but is always hidden.
  36. Versioning Objects
  37. ------------------
  38. JMSSerializerBundle comes by default with a very neat feature which allows
  39. you to add versioning support to your objects, e.g. if you want to
  40. expose them via an API that is consumed by a third-party:
  41. .. code-block :: php
  42. <?php
  43. class VersionedObject
  44. {
  45. /**
  46. * @Until("1.0.x")
  47. */
  48. private $name;
  49. /**
  50. * @Since("1.1")
  51. * @SerializedName("name")
  52. */
  53. private $name2;
  54. }
  55. .. note ::
  56. ``@Until``, and ``@Since`` both accept a standardized PHP version number.
  57. If you have annotated your objects like above, you can serializing different
  58. versions like this::
  59. use JMS\Serializer\SerializationContext;
  60. $serializer->serialize(new VersionObject(), 'json', SerializationContext::create()->setVersion(1));
  61. Creating Different Views of Your Objects
  62. ----------------------------------------
  63. Another default exclusion strategy is to create different views of your objects.
  64. Let's say you would like to serialize your object in a different view depending
  65. whether it is displayed in a list view or in a details view.
  66. You can achieve that by using the ``@Groups`` annotation on your properties. Any
  67. property without an explicit ``@Groups`` annotation will be included in a
  68. ``Default`` group, which can be used when specifying groups in the serialization
  69. context.
  70. .. code-block :: php
  71. use JMS\Serializer\Annotation\Groups;
  72. class BlogPost
  73. {
  74. /** @Groups({"list", "details"}) */
  75. private $id;
  76. /** @Groups({"list", "details"}) */
  77. private $title;
  78. /** @Groups({"list"}) */
  79. private $nbComments;
  80. /** @Groups({"details"}) */
  81. private $comments;
  82. private $createdAt;
  83. }
  84. You can then tell the serializer which groups to serialize in your controller::
  85. use JMS\Serializer\SerializationContext;
  86. $serializer->serialize(new BlogPost(), 'json', SerializationContext::create()->setGroups(array('list')));
  87. //will output $id, $title and $nbComments.
  88. $serializer->serialize(new BlogPost(), 'json', SerializationContext::create()->setGroups(array('Default', 'list')));
  89. //will output $id, $title, $nbComments and $createdAt.
  90. Overriding Groups of Deeper Branches of the Graph
  91. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  92. In some cases you want to control more precisely what is serialized because you may have the same class at different
  93. depths of the object graph.
  94. For example if you have a User that has a manager and friends::
  95. use JMS\Serializer\Annotation\Groups;
  96. class User
  97. {
  98. private $name;
  99. /** @Groups({"manager_group"}) */
  100. private $manager;
  101. /** @Groups({"friends_group"}) */
  102. private $friends;
  103. public function __construct($name, User $manager = null, array $friends = null)
  104. {
  105. $this->name = $name;
  106. $this->manager = $manager;
  107. $this->friends = $friends;
  108. }
  109. }
  110. And the following object graph::
  111. $john = new User(
  112. 'John',
  113. new User(
  114. 'John Manager',
  115. new User('The boss'),
  116. array(
  117. new User('John Manager friend 1'),
  118. )
  119. ),
  120. array(
  121. new User(
  122. 'John friend 1',
  123. new User('John friend 1 manager')
  124. ),
  125. new User(
  126. 'John friend 2',
  127. new User('John friend 2 manager')
  128. ),
  129. )
  130. );
  131. You can override groups on specific paths::
  132. use JMS\Serializer\SerializationContext;
  133. $context = SerializationContext::create()->setGroups(array(
  134. 'Default', // Serialize John's name
  135. 'manager_group', // Serialize John's manager
  136. 'friends_group', // Serialize John's friends
  137. 'manager' => array( // Override the groups for the manager of John
  138. 'Default', // Serialize John manager's name
  139. 'friends_group', // Serialize John manager's friends. If you do not override the groups for the friends, it will default to Default.
  140. ),
  141. 'friends' => array( // Override the groups for the friends of John
  142. 'manager_group' // Serialize John friends' managers.
  143. 'manager' => array( // Override the groups for the John friends' manager
  144. 'Default', // This would be the default if you did not override the groups of the manager property.
  145. ),
  146. ),
  147. ));
  148. $serializer->serialize($john, 'json', $context);
  149. This would result in the following json::
  150. {
  151. "name": "John",
  152. "manager": {
  153. "name": "John Manager",
  154. "friends": [
  155. {
  156. "name": "John Manager friend 1"
  157. }
  158. ]
  159. },
  160. "friends": [
  161. {
  162. "manager": {
  163. "name": "John friend 1 manager"
  164. },
  165. },
  166. {
  167. "manager": {
  168. "name": "John friend 2 manager"
  169. },
  170. },
  171. ]
  172. }
  173. Limiting serialization depth of some properties
  174. -----------------------------------------------
  175. You can limit the depth of what will be serialized in a property with the
  176. ``@MaxDepth`` annotation.
  177. This exclusion strategy is a bit different from the others, because it will
  178. affect the serialized content of others classes than the one you apply the
  179. annotation to.
  180. .. code-block :: php
  181. use JMS\Serializer\Annotation\MaxDepth;
  182. class User
  183. {
  184. private $username;
  185. /** @MaxDepth(1) */
  186. private $friends;
  187. /** @MaxDepth(2) */
  188. private $posts;
  189. }
  190. class Post
  191. {
  192. private $title;
  193. private $author;
  194. }
  195. In this example, serializing a user, because the max depth of the ``$friends``
  196. property is 1, the user friends would be serialized, but not their friends;
  197. and because the the max depth of the ``$posts`` property is 2, the posts would
  198. be serialized, and their author would also be serialized.
  199. You need to tell the serializer to take into account MaxDepth checks::
  200. use JMS\Serializer\SerializationContext;
  201. $serializer->serialize($data, 'json', SerializationContext::create()->enableMaxDepthChecks());
  202. Dynamic exclusion strategy
  203. --------------------------
  204. If the previous exclusion strategies are not enough, is possible to use the ``ExpressionLanguageExclusionStrategy``
  205. that uses the `symfony expression language`_ to
  206. allow a more sophisticated exclusion strategies using ``@Exclude(if="expression")`` and ``@Expose(if="expression")`` methods.
  207. .. code-block :: php
  208. <?php
  209. class MyObject
  210. {
  211. /**
  212. * @Exclude(if="true")
  213. */
  214. private $name;
  215. /**
  216. * @Expose(if="true")
  217. */
  218. private $name2;
  219. }
  220. .. note ::
  221. ``true`` is just a generic expression, you can use any expression allowed by the Symfony Expression Language
  222. To enable this feature you have to set the Expression Evaluator when initializing the serializer.
  223. .. code-block :: php
  224. <?php
  225. use JMS\Serializer\Expression\ExpressionEvaluator;
  226. use JMS\Serializer\Expression\SerializerBuilder;
  227. use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
  228. $serializer = SerializerBuilder::create()
  229. ->setExpressionEvaluator(new ExpressionEvaluator(new ExpressionLanguage()))
  230. ->build();
  231. .. _symfony expression language: https://github.com/symfony/expression-language