Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Kévin Dunglas

May 17, 2018
Tweet

More Decks by Kévin Dunglas

Other Decks in Technology

Transcript

  1. @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
  2. @dunglas - Les-Tilleuls.coop Dev, consulting and training (Masterclass) Self-managed since

    2011 ⬆ 97% in 2016, 25 people sharing benefits ➡ [email protected] Les-Tilleuls.coop 3
  3. @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 “ ”
  4. @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
  5. @dunglas - Les-Tilleuls.coop They Use the Serializer Component 7 New

    in Symfony 4.1: the Messenger component also uses the Serializer
  6. @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
  7. @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
  8. @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
  9. @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.
  10. @dunglas - Les-Tilleuls.coop An Object Mixing Public Props and Accessors

    Unfortunately neither PropertyNormalizer nor GetSetMethodNormalizer can deal with this object. ObjectNormalizer can! 46
  11. @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.
  12. @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
  13. @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
  14. @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.
  15. @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
  16. @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
  17. @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
  18. @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
  19. @dunglas - Les-Tilleuls.coop Type Safety 81 This behavior can be

    disabled with the ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT context key.
  20. @dunglas - Les-Tilleuls.coop Registration and Usage 100 ❏ Conference instances

    will be normalized by the ConferenceNormalizer ❏ All other objects by the PropertyNormalizer ❏ Order matters!
  21. @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
  22. @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
  23. @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