Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

@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

Slide 3

Slide 3 text

@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

Slide 4

Slide 4 text

@dunglas - Les-Tilleuls.coop Introduction 4

Slide 5

Slide 5 text

@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 “ ”

Slide 6

Slide 6 text

@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

Slide 7

Slide 7 text

@dunglas - Les-Tilleuls.coop They Use the Serializer Component 7 New in Symfony 4.1: the Messenger component also uses the Serializer

Slide 8

Slide 8 text

@dunglas - Les-Tilleuls.coop 8 Now 14,735 LOC History

Slide 9

Slide 9 text

@dunglas - Les-Tilleuls.coop Architecture 9

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

@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

Slide 12

Slide 12 text

@dunglas - Les-Tilleuls.coop Basic Usage 12

Slide 13

Slide 13 text

@dunglas - Les-Tilleuls.coop Standalone Installation 13

Slide 14

Slide 14 text

@dunglas - Les-Tilleuls.coop Basic Initialization 14

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

@dunglas - Les-Tilleuls.coop Alternatives? 17

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

@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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

@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

Slide 23

Slide 23 text

@dunglas - Les-Tilleuls.coop Serialization: From a PHP Object to an Open Format 23

Slide 24

Slide 24 text

@dunglas - Les-Tilleuls.coop A Dummy Object 24

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

@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.

Slide 44

Slide 44 text

@dunglas - Les-Tilleuls.coop 44

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

@dunglas - Les-Tilleuls.coop An Object Mixing Public Props and Accessors Unfortunately neither PropertyNormalizer nor GetSetMethodNormalizer can deal with this object. ObjectNormalizer can! 46

Slide 47

Slide 47 text

@dunglas - Les-Tilleuls.coop ObjectNormalizer: The Power of PropertyAccess 47

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

@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.

Slide 50

Slide 50 text

@dunglas - Les-Tilleuls.coop Adding More Properties to Our Class 50

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

@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

Slide 53

Slide 53 text

@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

Slide 54

Slide 54 text

@dunglas - Les-Tilleuls.coop Built-In Encoders 54

Slide 55

Slide 55 text

@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.

Slide 56

Slide 56 text

@dunglas - Les-Tilleuls.coop Registering All Built-In Encoders 56

Slide 57

Slide 57 text

@dunglas - Les-Tilleuls.coop XML 57

Slide 58

Slide 58 text

@dunglas - Les-Tilleuls.coop CSV 58

Slide 59

Slide 59 text

@dunglas - Les-Tilleuls.coop YAML 59

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

@dunglas - Les-Tilleuls.coop Defining The Groups 61 XML, YAML and plain PHP are also supported

Slide 62

Slide 62 text

@dunglas - Les-Tilleuls.coop Providing Metadata 62

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

@dunglas - Les-Tilleuls.coop Array Denormalization 68

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

@dunglas - Les-Tilleuls.coop Recursive Denormalization 71

Slide 72

Slide 72 text

@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

Slide 73

Slide 73 text

@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

Slide 74

Slide 74 text

@dunglas - Les-Tilleuls.coop 74

Slide 75

Slide 75 text

@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

Slide 76

Slide 76 text

@dunglas - Les-Tilleuls.coop Adding Type Metadata 76

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

@dunglas - Les-Tilleuls.coop Using Recursive Denormalization 78 Recursive array denormalization is also supported ✌

Slide 79

Slide 79 text

@dunglas - Les-Tilleuls.coop Type Safety 79

Slide 80

Slide 80 text

@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

Slide 81

Slide 81 text

@dunglas - Les-Tilleuls.coop Type Safety 81 This behavior can be disabled with the ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT context key.

Slide 82

Slide 82 text

@dunglas - Les-Tilleuls.coop 82

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

@dunglas - Les-Tilleuls.coop Circular References 88

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

@dunglas - Les-Tilleuls.coop Better Than an Infinite Recursion... 90

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

@dunglas - Les-Tilleuls.coop Abstract Classes 97

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

@dunglas - Les-Tilleuls.coop Registration and Usage 100 ❏ Conference instances will be normalized by the ConferenceNormalizer ❏ All other objects by the PropertyNormalizer ❏ Order matters!

Slide 101

Slide 101 text

@dunglas - Les-Tilleuls.coop Symfony 4 Integration 101

Slide 102

Slide 102 text

@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

Slide 103

Slide 103 text

@dunglas - Les-Tilleuls.coop 103 Merci joind.in/talk/bbc64 A demain, 9h30 salle Jarvis

Slide 104

Slide 104 text

@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

Slide 105

Slide 105 text

@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