Pro Yearly is on sale from $80 to $50! »

Mastering the Symfony Serializer

Mastering the Symfony Serializer

The Symfony Serializer Component exists since the very beginning of Symfony 2. Years after years, it gained a lot of new features useful to transform various data formats to PHP structures and the opposite. It is also a foundation block of API Platform and a first-class citizen in FOSRest.

Let's dive into this component. We will cover the basic concepts behind the serialization process: normalization, denormalization, encoding and decoding.

Then we will discover all the little known features of the component: JSON, XML and CSV support, file handling with "data:" URIs, serialization groups, attributes names conversion, trees support, updating existing objects, dealing with circular references.

Finally we will learn how to create custom normalizers and encoders; and how to modify the behavior of the builtin ones using composition.

E66449b8260b07a1cf51c5ab5eaa8180?s=128

Kévin Dunglas

May 17, 2018
Tweet

Transcript

  1. @dunglas - Les-Tilleuls.coop Mastering the Symfony Serializer 1

  2. @dunglas - Les-Tilleuls.coop Kévin Dunglas ❏ Co-founder of Les-Tilleuls.coop ❏

    Symfony Core Team (Serializer, PropertyInfo, WebLink, autowiring, PSR-7 Bridge…) ❏ Creator of API Platform 2 @dunglas
  3. @dunglas - Les-Tilleuls.coop Dev, consulting and training (Masterclass) Self-managed since

    2011 ⬆ 97% in 2016, 25 people sharing benefits ➡ jobs@les-tilleuls.coop Les-Tilleuls.coop 3
  4. @dunglas - Les-Tilleuls.coop Introduction 4

  5. @dunglas - Les-Tilleuls.coop The Serializer component is meant to be

    used to turn objects into a specific format (XML, JSON, YAML, ...) and the other way around. 5 “ ”
  6. @dunglas - Les-Tilleuls.coop Most popular use case: retrieve/send data from/to

    external systems ❏ Create web APIs ❏ Hydrate objects from DB results or external API responses ❏ Exchange data between apps (or [micro]services) 6
  7. @dunglas - Les-Tilleuls.coop They Use the Serializer Component 7 New

    in Symfony 4.1: the Messenger component also uses the Serializer
  8. @dunglas - Les-Tilleuls.coop 8 Now 14,735 LOC History

  9. @dunglas - Les-Tilleuls.coop Architecture 9

  10. @dunglas - Les-Tilleuls.coop Normalization and Encoding 10

  11. @dunglas - Les-Tilleuls.coop ChainNormalizer and ChainEncoder ❏ A list of

    normalizers and encoders are passed to the Serializer’s constructor ❏ The 1st implementation having a supports* method returning true is used ❏ Extension point to register custom implems for specific classes or formats 11
  12. @dunglas - Les-Tilleuls.coop Basic Usage 12

  13. @dunglas - Les-Tilleuls.coop Standalone Installation 13

  14. @dunglas - Les-Tilleuls.coop Basic Initialization 14

  15. @dunglas - Les-Tilleuls.coop Basic Usage: Serialization 15

  16. @dunglas - Les-Tilleuls.coop Basic Usage: Deserialization 16

  17. @dunglas - Les-Tilleuls.coop Alternatives? 17

  18. @dunglas - Les-Tilleuls.coop Why Not PHP’s (un)?serialize? 18

  19. @dunglas - Les-Tilleuls.coop Why Not PHP’s (un)?serialize? Super fast, and

    preserve types, but… ❏ Not interoperable ❏ Not secure for non-internal use ↓ 19
  20. @dunglas - Les-Tilleuls.coop Why Not PHP’s (un)?serialize? 20

  21. @dunglas - Les-Tilleuls.coop Why Not json_(en|de)code? 21

  22. @dunglas - Les-Tilleuls.coop Why Not json_(en|de)code? ❏ Cannot hydrate non-anonymous

    objects when decoding ❏ Limited feature set (groups, circular references, trees…) Symfony Serializer’s JSON encoder uses json_encode/json_decode internally. 22
  23. @dunglas - Les-Tilleuls.coop Serialization: From a PHP Object to an

    Open Format 23
  24. @dunglas - Les-Tilleuls.coop A Dummy Object 24

  25. @dunglas - Les-Tilleuls.coop From an object, to an associative array

    Normalization 25
  26. @dunglas - Les-Tilleuls.coop Normalization: From an Object To an Array

    26
  27. @dunglas - Les-Tilleuls.coop The Serializer is also a Normalizer 27

  28. @dunglas - Les-Tilleuls.coop From an array, to the output format

    Encoding 28
  29. @dunglas - Les-Tilleuls.coop Encoding: From an Array to a String

    29
  30. @dunglas - Les-Tilleuls.coop The Serializer is also an Encoder 30

  31. @dunglas - Les-Tilleuls.coop Normalization => Encoding Serialization 31

  32. @dunglas - Les-Tilleuls.coop Serialization: Normalization + Encoding 32

  33. @dunglas - Les-Tilleuls.coop Deserialization: From an Open Format To a

    PHP Object 33
  34. @dunglas - Les-Tilleuls.coop From a String to an Array Decoding

    34
  35. @dunglas - Les-Tilleuls.coop Decoding: From a String to an Array

    35
  36. @dunglas - Les-Tilleuls.coop The Serializer is also a Decoder 36

  37. @dunglas - Les-Tilleuls.coop From an Array to an Object Denormalization

    37
  38. @dunglas - Les-Tilleuls.coop Denormalization: From an Array to an Object

    38
  39. @dunglas - Les-Tilleuls.coop The Serializer is also a Denormalizer 39

  40. @dunglas - Les-Tilleuls.coop Decoding => Denormalization Deserialization 40

  41. @dunglas - Les-Tilleuls.coop Deserialization: Decoding + Denormalization 41

  42. @dunglas - Les-Tilleuls.coop Different kinds of Object Normalizers 42

  43. @dunglas - Les-Tilleuls.coop Native Object Normalizers 43 Access Data Supports

    Dependencies PropertyNormalizer Public properties - GetSetMethodNormalizer get / set, is / has - ObjectNormalizer Public properties get / set, is / has add / remove __call (opt-in) __get (opt-in) symfony/property-access optional, but boosts perf: symfony/cache ObjectNormalizer is the smartest generic normalizer. It is enabled by default when using Symfony full stack.
  44. @dunglas - Les-Tilleuls.coop 44

  45. @dunglas - Les-Tilleuls.coop An Object Mixing Public Props and Accessors

    45
  46. @dunglas - Les-Tilleuls.coop An Object Mixing Public Props and Accessors

    Unfortunately neither PropertyNormalizer nor GetSetMethodNormalizer can deal with this object. ObjectNormalizer can! 46
  47. @dunglas - Les-Tilleuls.coop ObjectNormalizer: The Power of PropertyAccess 47

  48. @dunglas - Les-Tilleuls.coop Normalizers for Specific Types 48

  49. @dunglas - Les-Tilleuls.coop Normalizers for Special Objects 49 Supported Objects

    Dependency DataUriNormalizer File <-> data: URI \SplFileInfo \SplFileObject HttpFoundation’s File optional, to guess MIME types: symfony/ http-foundation DateIntervalNormalizer Date interval <-> ISO 8601 string \DateInterval - DateTimeNormalizer Date & time <-> ISO 8601 string \DateTimeInterface - Since 4.1 ConstraintViolationListNormalizer Validation errors -> RFC 7807 (API Problem Details) Validator’s ConstraintViolationListInterface symfony/validator JsonSerializableNormalizer Json_encode’s like JsonSerializable \JsonSerializable - They are all available by default when using the Symfony full stack framework.
  50. @dunglas - Les-Tilleuls.coop Adding More Properties to Our Class 50

  51. @dunglas - Les-Tilleuls.coop Registering and Using Specific Normalizers 51

  52. @dunglas - Les-Tilleuls.coop Recursive Normalization: Thanks to the Chain of

    Responsibility ❏ Generic object normalizers implement the SerializerAwareInterface ❏ They recursively call Serializer::normalize() for all values they normalize 52
  53. @dunglas - Les-Tilleuls.coop Recursive Normalization: Thanks to the Chain of

    Responsibility In our previous example: ❏ Conference is normalized by ObjectNormalizer ❏ Because supportsNormalization() method of normalizers registered before it return false ❏ DateTime by DateTimeNormalizer ❏ SplFileObject by DataUriNormalizer 53
  54. @dunglas - Les-Tilleuls.coop Built-In Encoders 54

  55. @dunglas - Les-Tilleuls.coop Built-In Encoders and Decoders 55 Format Dependencies

    JsonEncoder JSON - XmlEncoder XML - CsvEncoder CSV - YamlEncoder YAML symfony/yaml They are all available by default when using the Symfony full stack framework.
  56. @dunglas - Les-Tilleuls.coop Registering All Built-In Encoders 56

  57. @dunglas - Les-Tilleuls.coop XML 57

  58. @dunglas - Les-Tilleuls.coop CSV 58

  59. @dunglas - Les-Tilleuls.coop YAML 59

  60. @dunglas - Les-Tilleuls.coop Select just some properties Serialization Groups 60

  61. @dunglas - Les-Tilleuls.coop Defining The Groups 61 XML, YAML and

    plain PHP are also supported
  62. @dunglas - Les-Tilleuls.coop Providing Metadata 62

  63. @dunglas - Les-Tilleuls.coop Serialization Group: conference:list 63

  64. @dunglas - Les-Tilleuls.coop Serialization Group: conference:item 64

  65. @dunglas - Les-Tilleuls.coop Serialization Groups: None (default behavior) 65

  66. @dunglas - Les-Tilleuls.coop Do you know GraphQL? Select Specific Attributes

    66
  67. @dunglas - Les-Tilleuls.coop Select Specific Attributes 67

  68. @dunglas - Les-Tilleuls.coop Array Denormalization 68

  69. @dunglas - Les-Tilleuls.coop Registering the ArrayDenormalizer 69

  70. @dunglas - Les-Tilleuls.coop Using The Array Denormalizer 70

  71. @dunglas - Les-Tilleuls.coop Recursive Denormalization 71

  72. @dunglas - Les-Tilleuls.coop Recursive Denormalization Recursive normalization works out of

    the box (thanks to the SerializerAwareInterface). Unfortunately, this is not the case for denormalization: 72
  73. @dunglas - Les-Tilleuls.coop Recursive Denormalization The Serializer cannot guess that:

    ❏ date must be denormalized as a \DateTime (and not a string) ❏ logo as a \SplFileObject (and not a string) 73
  74. @dunglas - Les-Tilleuls.coop 74

  75. @dunglas - Les-Tilleuls.coop PropertyInfo: Type Metadata Sources 75 Dependencies Getter

    / Setter / Adder / Remover / Constructor - PHPDoc phpdocumentator/reflection-docblock Doctrine ORM mappings symfony/doctrine-bridge Optional but boosts perf: symfony/cache
  76. @dunglas - Les-Tilleuls.coop Adding Type Metadata 76

  77. @dunglas - Les-Tilleuls.coop Registering the PropertyInfo Type Extractor 77

  78. @dunglas - Les-Tilleuls.coop Using Recursive Denormalization 78 Recursive array denormalization

    is also supported ✌
  79. @dunglas - Les-Tilleuls.coop Type Safety 79

  80. @dunglas - Les-Tilleuls.coop Type Safety Bonus: If a PropertyInfo Type

    extractor is registered, the built-in object normalizers will also ensure that the type of the data to deserialize matches the intended one! 80
  81. @dunglas - Les-Tilleuls.coop Type Safety 81 This behavior can be

    disabled with the ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT context key.
  82. @dunglas - Les-Tilleuls.coop 82

  83. @dunglas - Les-Tilleuls.coop Updating an Existing Object 83

  84. @dunglas - Les-Tilleuls.coop Updating an Existing Object 84

  85. @dunglas - Les-Tilleuls.coop The Perfect Match for Value Objects Hydrating

    Through the Constructor 85
  86. @dunglas - Les-Tilleuls.coop Hydrating Through the Constructor 86

  87. @dunglas - Les-Tilleuls.coop Providing Default Values (new in 4.1) 87

  88. @dunglas - Les-Tilleuls.coop Circular References 88

  89. @dunglas - Les-Tilleuls.coop A Model with a Circular Reference (avoid

    when you can) 89
  90. @dunglas - Les-Tilleuls.coop Better Than an Infinite Recursion... 90

  91. @dunglas - Les-Tilleuls.coop Registering a Handler 91

  92. @dunglas - Les-Tilleuls.coop Configuring the Trigger Limit 92

  93. @dunglas - Les-Tilleuls.coop Trees and Max Depth 93

  94. @dunglas - Les-Tilleuls.coop A Tree, with a Serialization Max Depth

    94
  95. @dunglas - Les-Tilleuls.coop Serializing Tree With Max Depth 95

  96. @dunglas - Les-Tilleuls.coop New in 4.1: Registering a Handler 96

  97. @dunglas - Les-Tilleuls.coop Abstract Classes 97

  98. @dunglas - Les-Tilleuls.coop Creating Custom Normalizers 98

  99. @dunglas - Les-Tilleuls.coop A Normalizer For a Specific Class 99

  100. @dunglas - Les-Tilleuls.coop Registration and Usage 100 ❏ Conference instances

    will be normalized by the ConferenceNormalizer ❏ All other objects by the PropertyNormalizer ❏ Order matters!
  101. @dunglas - Les-Tilleuls.coop Symfony 4 Integration 101

  102. @dunglas - Les-Tilleuls.coop Typehint SerializerInterface anywhere, A fully featured Serializer

    is injected: ❏ All built-in normalizers and encoders ❏ PropertyInfo and PropertyAccess related features ❏ MetadataLoader with annotation, XML and YAML support 102
  103. @dunglas - Les-Tilleuls.coop 103 Merci joind.in/talk/bbc64 A demain, 9h30 salle

    Jarvis
  104. @dunglas - Les-Tilleuls.coop Also New in Symfony 4.1 ❏ Support

    for abstract classes (DiscriminatorMap) ❏ Massive performance improvements (+30%) ❏ Bunch of new options for the XML and CSV encoders 104
  105. @dunglas - Les-Tilleuls.coop A True Alternative: jms/serializer 105 Symfony JMS

    Pattern normalizer + encoder Chain of responsibility Visitor License MIT: permissive, compatible with most other (F)OSS licenses Apache v2: permissive, but incompatible with GPLv2 (Drupal, Wordpress, Joomla) V2 will be MIT: schmittjoh/serializer#950 Formats Core: JSON, XML, YAML, CSV, data: URI, RFC7807, ISO8601 API Platform: JSON-LD, HAL, Swagger, Hydra JSON, XML Maintainers SF Core Team (15 people) 2 people (1 active) Release process Semver, guaranteed upgrade path, time based release, strong BC policy Semver