index.rst 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. ========
  2. Overview
  3. ========
  4. This bundle allows you to easily serialize/unserialize objects. Main features
  5. include:
  6. - able to handle circular references, and object graphs of any depth without
  7. writing a single line of code
  8. - serialize/unserialize objects using annotations to describe metadata
  9. - supports versioning out of the box
  10. - easily customizable as most logic is implemented using clearly defined
  11. interfaces
  12. - can be configured via annotations, YAML, XML, or PHP
  13. Installation
  14. ------------
  15. First, checkout a copy of the code. Just add the following to the ``deps``
  16. file of your Symfony Standard Distribution::
  17. [JMSSerializerBundle]
  18. git=git://github.com/schmittjoh/JMSSerializerBundle.git
  19. target=bundles/JMS/SerializerBundle
  20. Then register the bundle with your kernel::
  21. // in AppKernel::registerBundles()
  22. $bundles = array(
  23. // ...
  24. new JMS\SerializerBundle\JMSSerializerBundle($this),
  25. // ...
  26. );
  27. This bundle also requires the Metadata library (**you need the 1.1 version, not the 1.0
  28. version** which ships with the Symfony Standard Edition.)::
  29. [metadata]
  30. git=http://github.com/schmittjoh/metadata.git
  31. version=1.1.0
  32. Make sure that you also register the namespaces with the autoloader::
  33. // app/autoload.php
  34. $loader->registerNamespaces(array(
  35. // ...
  36. 'JMS' => __DIR__.'/../vendor/bundles',
  37. 'Metadata' => __DIR__.'/../vendor/metadata/src',
  38. // ...
  39. ));
  40. Now use the ``vendors`` script to clone the newly added repositories
  41. into your project::
  42. php bin/vendors install
  43. Configuration
  44. -------------
  45. Below is the default configuration, you don't need to change it unless it doesn't
  46. suit your needs::
  47. jms_serializer:
  48. handlers:
  49. object_based: false
  50. datetime:
  51. format: <ISO8601 (Y-m-dTH:i:s)>
  52. default_timezone: <timezone set in php.ini or via date_default_timezone_set>
  53. array_collection: true
  54. form_error: true
  55. constraint_violation: true
  56. property_naming:
  57. separator: _
  58. lower_case: true
  59. metadata:
  60. cache: file
  61. debug: %kernel.debug%
  62. file_cache:
  63. dir: %kernel.cache_dir%/serializer
  64. # Using auto-detection, the mapping files for each bundle will be
  65. # expected in the Resources/config/serializer directory.
  66. #
  67. # Example:
  68. # class: My\FooBundle\Entity\User
  69. # expected path: @MyFooBundle/Resources/config/serializer/Entity.User.(yml|xml|php)
  70. auto_detection: true
  71. # if you don't want to use auto-detection, you can also define the
  72. # namespace prefix and the corresponding directory explicitly
  73. directories:
  74. any-name:
  75. namespace_prefix: My\FooBundle
  76. path: @MyFooBundle/Resources/config/serializer
  77. another-name:
  78. namespace_prefix: My\BarBundle
  79. path: @MyBarBundle/Resources/config/serializer
  80. Note the order in which the handlers are listed in the "handlers" section defines
  81. in which they are called while processing. See "extending.rst" for details for how
  82. to define custom handlers, which then also need to be configured as shown here.
  83. Usage
  84. -----
  85. De-/Serializing Objects
  86. ~~~~~~~~~~~~~~~~~~~~~~~
  87. ::
  88. $serializer = $container->get('serializer');
  89. $serializer->serialize(new MyObject(), 'json');
  90. $serializer->serialize(new MyObject(), 'xml');
  91. The serializer supports JSON, and XML out-of-the-box, and can also handle
  92. many custom XML features (see below).
  93. The serializer can also be accessed via a Twig filter and will default to
  94. "json"::
  95. {{ myObject | serialize | raw }}
  96. {{ myObject | serialize('xml') | raw }}
  97. Overriding Metadata
  98. ~~~~~~~~~~~~~~~~~~~
  99. Sometimes you want to serialize objects which are shipped by a third-party bundle.
  100. Such a third-party bundle might not ship with metadata that suits your needs, or
  101. possibly none, at all. In such a case, you can override the default location that
  102. is searched for metadata with a path that is under your control.
  103. ::
  104. jms_serializer:
  105. metadata:
  106. directories:
  107. FOSUB:
  108. namespace_prefix: FOS\UserBundle
  109. path: %kernel.root_dir%/serializer/FOSUB
  110. Versioning
  111. ~~~~~~~~~~
  112. The bundle allows you to have different versions of your objects. This can be
  113. achieved by using the @Since, and @Until annotation which both accept a
  114. standardized PHP version number.
  115. ::
  116. <?php
  117. class VersionedObject
  118. {
  119. /**
  120. * @Until("1.0.x")
  121. */
  122. private $name;
  123. /**
  124. * @Since("1.1")
  125. * @SerializedName("name")
  126. */
  127. private $name2;
  128. }
  129. If you have annotated your objects like above, you can serializing different
  130. versions like this::
  131. <?php
  132. $serializer->setVersion('1.0');
  133. $serializer->serialize(new VersionObject(), 'json');
  134. Defining which properties should be serialized
  135. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  136. The default exclusion policy is to exclude nothing, that is all properties of the
  137. object will be serialized. If you only want to expose a few of the properties,
  138. then it is easier to change the exclusion policy, and only mark these few properties::
  139. <?php
  140. use JMS\SerializerBundle\Annotation\ExclusionPolicy;
  141. use JMS\SerializerBundle\Annotation\Expose;
  142. /**
  143. * The following annotations tells the serializer to skip all properties which
  144. * have not marked with @Expose.
  145. *
  146. * @ExclusionPolicy("all")
  147. */
  148. class MyObject
  149. {
  150. private $foo;
  151. private $bar;
  152. /**
  153. * @Expose
  154. */
  155. private $name;
  156. }
  157. Lifecycle Callbacks
  158. ~~~~~~~~~~~~~~~~~~~
  159. If you need to run some custom logic during the serialization process, you can use
  160. one of these lifecycle callbacks: @PreSerialize, @PostSerialize, or @PostDeserialize
  161. Annotations
  162. -----------
  163. @ExclusionPolicy
  164. ~~~~~~~~~~~~~~~~
  165. This annotation can be defined on a class to indicate the exclusion strategy
  166. that should be used for the class.
  167. +----------+----------------------------------------------------------------+
  168. | Policy | Description |
  169. +==========+================================================================+
  170. | all | all properties are excluded by default; only properties marked |
  171. | | with @Expose will be serialized/unserialized |
  172. +----------+----------------------------------------------------------------+
  173. | none | no properties are excluded by default; all properties except |
  174. | | those marked with @Exclude will be serialized/unserialized |
  175. +----------+----------------------------------------------------------------+
  176. @Exclude
  177. ~~~~~~~~
  178. This annotation can be defined on a property to indicate that the property should
  179. not be serialized/unserialized. Works only in combination with NoneExclusionPolicy.
  180. @Expose
  181. ~~~~~~~
  182. This annotation can be defined on a property to indicate that the property should
  183. be serialized/unserialized. Works only in combination with AllExclusionPolicy.
  184. @SerializedName
  185. ~~~~~~~~~~~~~~~
  186. This annotation can be defined on a property to define the serialized name for a
  187. property. If this is not defined, the property will be translated from camel-case
  188. to a lower-cased underscored name, e.g. camelCase -> camel_case.
  189. @Since
  190. ~~~~~~
  191. This annotation can be defined on a property to specify starting from which
  192. version this property is available. If an earlier version is serialized, then
  193. this property is excluded automatically. The version must be in a format that is
  194. understood by PHP's ``version_compare`` function.
  195. @Until
  196. ~~~~~~
  197. This annotation can be defined on a property to specify until which version this
  198. property was available. If a later version is serialized, then this property is
  199. excluded automatically. The version must be in a format that is understood by
  200. PHP's ``version_compare`` function.
  201. @AccessType
  202. ~~~~~~~~~~~
  203. This annotation can be defined on a property, or a class to specify in which way
  204. the properties should be accessed. By default, the serializer will retrieve, or
  205. set the value via reflection, but you may change this to use a public method instead::
  206. /** @AccessType("public_method") */
  207. class User
  208. {
  209. private $name;
  210. public function getName()
  211. {
  212. return $this->name;
  213. }
  214. public function setName($name)
  215. {
  216. $this->name = trim($name);
  217. }
  218. }
  219. @Accessor
  220. ~~~~~~~~~
  221. This annotation can be defined on a property to specify which public method should
  222. be called to retrieve, or set the value of the given property::
  223. class User
  224. {
  225. private $id;
  226. /** @Accessor(getter="getTrimmedName") */
  227. private $name;
  228. // ...
  229. public function getTrimmedName()
  230. {
  231. return trim($this->name);
  232. }
  233. public function setName($name)
  234. {
  235. $this->name = $name;
  236. }
  237. }
  238. @AccessorOrder
  239. ~~~~~~~~~~~~~~
  240. This annotation can be defined on a class to control the order of properties. By
  241. default the order is undefined, but you may change it to either "alphabetical", or
  242. "custom".
  243. ::
  244. /**
  245. * @AccessorOrder("alphabetical")
  246. *
  247. * Resulting Property Order: id, name
  248. */
  249. class User
  250. {
  251. private $id;
  252. private $name;
  253. }
  254. /**
  255. * @AccessorOrder("custom", custom = {"name", "id"})
  256. *
  257. * Resulting Property Order: name, id
  258. */
  259. class User
  260. {
  261. private $id;
  262. private $name;
  263. }
  264. @Inline
  265. ~~~~~~~~
  266. This annotation can be defined on a property to indicate that the property should
  267. be serialized inline. AccessorOrder doesn't work when using inline annotation.
  268. NOTE: If the property contains properties with the same name, properties in parent will be overriden.
  269. @PreSerialize
  270. ~~~~~~~~~~~~~
  271. This annotation can be defined on a method which is supposed to be called before
  272. the serialization of the object starts.
  273. @PostSerialize
  274. ~~~~~~~~~~~~~~
  275. This annotation can be defined on a method which is then called directly after the
  276. object has been serialized.
  277. @PostDeserialize
  278. ~~~~~~~~~~~~~~~~
  279. This annotation can be defined on a method which is supposed to be called after
  280. the object has been deserialized.
  281. @Type
  282. ~~~~~
  283. This annotation can be defined on a property to specify the type of that property.
  284. This annotation must only be defined when you want to be able to deserialize an
  285. object.
  286. Available Types:
  287. +---------------------------+--------------------------------------------------+
  288. | Type | Description |
  289. +===========================+==================================================+
  290. | boolean | Primitive boolean |
  291. +---------------------------+--------------------------------------------------+
  292. | integer | Primitive integer |
  293. +---------------------------+--------------------------------------------------+
  294. | double | Primitive double |
  295. +---------------------------+--------------------------------------------------+
  296. | string | Primitive string |
  297. +---------------------------+--------------------------------------------------+
  298. | array | An array with arbitrary keys, and values. |
  299. +---------------------------+--------------------------------------------------+
  300. | array<T> | A list of type T (T can be any available type). |
  301. | | Examples: |
  302. | | array<string>, array<MyNamespace\MyObject>, etc. |
  303. +---------------------------+--------------------------------------------------+
  304. | array<K, V> | A map of keys of type K to values of type V. |
  305. | | Examples: array<string, string>, |
  306. | | array<string, MyNamespace\MyObject>, etc. |
  307. +---------------------------+--------------------------------------------------+
  308. | DateTime | PHP's DateTime object |
  309. +---------------------------+--------------------------------------------------+
  310. | T | Where T is a fully qualified class name. |
  311. +---------------------------+--------------------------------------------------+
  312. | ArrayCollection<T> | Similar to array<T>, but will be deserialized |
  313. | | into Doctrine's ArrayCollection class. |
  314. +---------------------------+--------------------------------------------------+
  315. | ArrayCollection<K, V> | Similar to array<K, V>, but will be deserialized |
  316. | | into Doctrine's ArrayCollection class. |
  317. +---------------------------+--------------------------------------------------+
  318. Examples::
  319. <?php
  320. namespace MyNamespace;
  321. use JMS\SerializerBundle\Annotation\Type;
  322. class BlogPost
  323. {
  324. /**
  325. * @Type("ArrayCollection<MyNamespace\Comment>")
  326. */
  327. private $comments;
  328. /**
  329. * @Type("string")
  330. */
  331. private $title;
  332. /**
  333. * @Type("MyNamespace\Author")
  334. */
  335. private $author;
  336. /**
  337. * @Type("DateTime")
  338. */
  339. private $createdAt;
  340. /**
  341. * @Type("boolean")
  342. */
  343. private $published;
  344. /**
  345. * @Type("array<string, string>")
  346. */
  347. private $keyValueStore;
  348. }
  349. @XmlRoot
  350. ~~~~~~~~
  351. This allows you to specify the name of the top-level element.
  352. ::
  353. <?php
  354. use JMS\SerializerBundle\Annotation\XmlRoot;
  355. /** @XmlRoot("user") */
  356. class User
  357. {
  358. private $name = 'Johannes';
  359. }
  360. Resulting XML::
  361. <user>
  362. <name><![CDATA[Johannes]]></name>
  363. </user>
  364. @XmlAttribute
  365. ~~~~~~~~~~~~~
  366. This allows you to mark properties which should be set as attributes,
  367. and not as child elements.
  368. ::
  369. <?php
  370. use JMS\SerializerBundle\Annotation\XmlAttribute;
  371. class User
  372. {
  373. /** @XmlAttribute */
  374. private $id = 1;
  375. private $name = 'Johannes';
  376. }
  377. Resulting XML::
  378. <result id="1">
  379. <name><![CDATA[Johannes]]></name>
  380. </result>
  381. @XmlValue
  382. ~~~~~~~~~
  383. This allows you to mark properties which should be set as the value of the
  384. current element. Note that this has the limitation that any additional
  385. properties of that object must have the @XmlAttribute annotation.
  386. ::
  387. <?php
  388. use JMS\SerializerBundle\Annotation\XmlAttribute;
  389. use JMS\SerializerBundle\Annotation\XmlValue;
  390. use JMS\SerializerBundle\Annotation\XmlRoot;
  391. /** @XmlRoot("price") */
  392. class Price
  393. {
  394. /** @XmlAttribute */
  395. private $currency = 'EUR';
  396. /** @XmlValue */
  397. private $amount = 1.23;
  398. }
  399. Resulting XML::
  400. <price currency="EUR">1.23</price>
  401. @XmlList
  402. ~~~~~~~~
  403. This allows you to define several properties of how arrays should be
  404. serialized. This is very similar to @XmlMap, and should be used if the
  405. keys of the array are not important.
  406. ::
  407. <?php
  408. use JMS\SerializerBundle\Annotation\XmlList;
  409. use JMS\SerializerBundle\Annotation\XmlRoot;
  410. /** @XmlRoot("post") */
  411. class Post
  412. {
  413. /**
  414. * @XmlList(inline = true, entry = "comment")
  415. */
  416. private $comments = array(
  417. new Comment('Foo'),
  418. new Comment('Bar'),
  419. );
  420. }
  421. class Comment
  422. {
  423. private $text;
  424. public function __construct($text)
  425. {
  426. $this->text = $text;
  427. }
  428. }
  429. Resulting XML::
  430. <post>
  431. <comment>
  432. <text><![CDATA[Foo]]></text>
  433. </comment>
  434. <comment>
  435. <text><![CDATA[Bar]]></text>
  436. </comment>
  437. </post>
  438. @XmlMap
  439. ~~~~~~~
  440. Similar to @XmlList, but the keys of the array are meaningful.
  441. XML Reference
  442. -------------
  443. ::
  444. <!-- MyBundle\Resources\config\serializer\ClassName.xml -->
  445. <?xml version="1.0" encoding="UTF-8">
  446. <serializer>
  447. <class name="Fully\Qualified\ClassName" exclusion-policy="ALL" xml-root-name="foo-bar" exclude="true"
  448. accessor-order="custom" custom-accessor-order="propertyName1,propertyName2,...,propertyNameN"
  449. access-type="public_method">
  450. <property name="some-property"
  451. exclude="true"
  452. expose="true"
  453. type="string"
  454. serialized-name="foo"
  455. since-version="1.0"
  456. until-version="1.1"
  457. xml-attribute="true"
  458. access-type="public_method"
  459. accessor-getter="getSomeProperty"
  460. accessor-setter="setSomeProperty"
  461. inline="true"
  462. >
  463. <!-- You can also specify the type as element which is necessary if
  464. your type contains "<" or ">" characters. -->
  465. <type><![CDATA[]]></type>
  466. <xml-list inline="true" entry-name="foobar" />
  467. <xml-map inline="true" key-attribute-name="foo" entry-name="bar" />
  468. </property>
  469. <callback-method name="foo" type="pre-serialize" />
  470. <callback-method name="bar" type="post-serialize" />
  471. <callback-method name="baz" type="post-deserialize" />
  472. </class>
  473. </serializer>
  474. YAML Reference
  475. --------------
  476. ::
  477. # MyBundle\Resources\config\serializer\ClassName.yml
  478. Fully\Qualified\ClassName:
  479. exclusion_policy: ALL
  480. xml_root_name: foobar
  481. exclude: true
  482. access_type: public_method # defaults to property
  483. accessor_order: custom
  484. custom_accessor_order: [propertyName1, propertyName2, ..., propertyNameN]
  485. properties:
  486. some-property:
  487. exclude: true
  488. expose: true
  489. access_type: public_method # defaults to property
  490. type: string
  491. serialized_name: foo
  492. since_version: 1.0
  493. until_version: 1.1
  494. xml_attribute: true
  495. inline: true
  496. xml_list:
  497. inline: true
  498. entry_name: foo
  499. xml_map:
  500. inline: true
  501. key_attribute_name: foo
  502. entry_name: bar
  503. callback_methods:
  504. pre_serialize: [foo, bar]
  505. post_serialize: [foo, bar]
  506. post_deserialize: [foo, bar]