You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: core/serialization.md
+82-14Lines changed: 82 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,20 +2,24 @@
2
2
3
3
## Overall Process
4
4
5
-
API Platform embraces and extends the Symfony Serializer Component to transform PHP entities in (hypermedia) API responses.
5
+
API Platform embraces and extends the Symfony Serializer Component & Eloquent Serialization to transform PHP entities in
6
+
(hypermedia) API responses.
6
7
7
8
<palign="center"class="symfonycasts"><ahref="https://symfonycasts.com/screencast/api-platform/serializer?cid=apip"><imgsrc="../symfony/images/symfonycasts-player.png"alt="Serializer screencast"><br>Watch the Serializer screencast</a></p>
> As you can see in the picture above, an array is used as a man-in-the-middle. This way, Encoders will only deal with turning specific formats into arrays and vice versa. The same way, Normalizers will deal with turning specific objects into arrays and vice versa.
Unlike Symfony itself, API Platform leverages custom normalizers, its router and the [state provider](state-providers.md) system to perform an advanced transformation. Metadata are added to the generated document including links, type information, pagination data or available filters.
17
+
Unlike Symfony or Laravel themselves, API Platform leverages custom normalizers, its router and the [state provider](state-providers.md)
18
+
system to perform an advanced transformation. Metadata are added to the generated document including links, type
19
+
information, pagination data or available filters.
17
20
18
-
The API Platform Serializer is extendable. You can register custom normalizers and encoders in order to support other formats. You can also decorate existing normalizers to customize their behaviors.
21
+
The API Platform Serializer is extendable. You can register custom normalizers and encoders in order to support other formats.
22
+
You can also decorate existing normalizers to customize their behaviors.
19
23
20
24
## Available Serializers
21
25
@@ -27,7 +31,7 @@ JSON-LD, or JavaScript Object Notation for Linked Data, is a method of encoding
- JSON, XML, CSV, YAML serializer (using the Symfony serializer)
34
+
- JSON, XML, CSV, YAML serializer (using the Symfony serializer or the Eloquent Serialization)
31
35
`api_platform.serializer.normalizer.item`
32
36
33
37
## The Serialization Context, Groups and Relations
@@ -41,7 +45,7 @@ feature of the Symfony Serializer component.
41
45
In addition to groups, you can use any option supported by the Symfony Serializer. For example, you can use [`enable_max_depth`](https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth)
42
46
to limit the serialization depth.
43
47
44
-
### Configuration
48
+
### Configuration for Symfony
45
49
46
50
Just like other Symfony and API Platform components, the Serializer component can be configured using attributes, XML
47
51
or YAML. Since attributes are easy to understand, we will use them in the following examples.
@@ -69,6 +73,9 @@ framework:
69
73
70
74
## Using Serialization Groups
71
75
76
+
> [!NOTE]
77
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
78
+
72
79
It is simple to specify what groups to use in the API system:
73
80
74
81
1. Add the normalization context and denormalization context attributes to the resource, and specify which groups to use. Here you see that we add `read` and `write`, respectively. You can use any group names you wish.
@@ -101,6 +108,7 @@ class Book
101
108
```
102
109
103
110
```yaml
111
+
# The YAML syntax is only supported for Symfony
104
112
# api/config/api_platform/resources.yaml
105
113
resources:
106
114
App\Entity\Book:
@@ -109,6 +117,7 @@ resources:
109
117
denormalizationContext:
110
118
groups: ['write']
111
119
120
+
# The YAML syntax is only supported for Symfony
112
121
# api/config/serialization/Book.yaml
113
122
App\Entity\Book:
114
123
attributes:
@@ -119,6 +128,7 @@ App\Entity\Book:
119
128
```
120
129
121
130
```xml
131
+
<!--The XML syntax is only supported for Symfony -->
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
200
+
201
+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/relations?cid=apip"><img src="../symfony/images/symfonycasts-player.png" alt="Relations screencast"><br>Watch the Relations screencast</a></p>
202
+
203
+
By default, the serializer provided with API Platform represents relations between objects using [dereferenceable IRIs](https://en.wikipedia.org/wiki/Internationalized_Resource_Identifier).
204
+
They allow you to retrieve details for related objects by issuing extra HTTP requests. However, for performance reasons, it is sometimes preferable to avoid forcing the client to issue extra HTTP requests.
205
+
206
+
187
207
It is possible to specify normalization and denormalization contexts (as well as any other attribute) on a per-operation
188
208
basis. API Platform will always use the most specific definition. For instance, if normalization groups are set both
189
209
at the resource level and at the operation level, the configuration set at the operation level will be used and the resource
@@ -219,6 +239,7 @@ class Book
219
239
```
220
240
221
241
```yaml
242
+
# The YAML syntax is only supported for Symfony
222
243
# api/config/api_platform/resources/Book.yaml
223
244
App\Entity\Book:
224
245
normalizationContext:
@@ -229,6 +250,7 @@ App\Entity\Book:
229
250
normalizationContext:
230
251
groups: ['patch']
231
252
253
+
# The YAML syntax is only supported for Symfony
232
254
# api/config/serializer/Book.yaml
233
255
App\Entity\Book:
234
256
attributes:
@@ -239,6 +261,7 @@ App\Entity\Book:
239
261
```
240
262
241
263
```xml
264
+
<!-- The XML syntax is only supported for Symfony -->
@@ -309,6 +333,9 @@ They allow you to retrieve details for related objects by issuing extra HTTP req
309
333
310
334
### Normalization
311
335
336
+
> [!NOTE]
337
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
338
+
312
339
In the following JSON document, the relation from a book to an author is by default represented by an URI:
313
340
314
341
```json
@@ -350,11 +377,13 @@ class Book
350
377
```
351
378
352
379
```yaml
380
+
# The YAML syntax is only supported for Symfony
353
381
# api/config/api_platform/resources/Book.yaml
354
382
App\Entity\Book:
355
383
normalizationContext:
356
384
groups: ['book']
357
385
386
+
# The YAML syntax is only supported for Symfony
358
387
# api/config/serializer/Book.yaml
359
388
App\Entity\Book:
360
389
attributes:
@@ -387,6 +416,7 @@ class Person
387
416
```
388
417
389
418
```yaml
419
+
# The YAML syntax is only supported for Symfony
390
420
# api/config/serializer/Person.yaml
391
421
App\Entity\Person:
392
422
attributes:
@@ -420,6 +450,9 @@ Instead of embedding relations in the main HTTP response, you may want [to "push
420
450
421
451
### Denormalization
422
452
453
+
> [!NOTE]
454
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
455
+
423
456
It is also possible to embed a relation in `PUT`, `PATCH` and `POST` requests. To enable that feature, set the serialization groups
424
457
the same way as normalization. For example:
425
458
@@ -440,6 +473,7 @@ class Book
440
473
```
441
474
442
475
```yaml
476
+
# The YAML syntax is only supported for Symfony
443
477
# api/config/api_platform/resources/Book.yaml
444
478
App\Entity\Book:
445
479
denormalizationContext:
@@ -458,6 +492,9 @@ You can specify as many embedded relation levels as you want.
458
492
459
493
### Force IRI with relations of the same type (parent/childs relations)
460
494
495
+
> [!NOTE]
496
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
497
+
461
498
It is a common problem to have entities that reference other entities of the same type:
462
499
463
500
<code-selector>
@@ -490,13 +527,15 @@ class Person
490
527
```
491
528
492
529
```yaml
530
+
# The YAML syntax is only supported for Symfony
493
531
# api/config/api_platform/resources/Person.yaml
494
532
App\Entity\Person:
495
533
normalizationContext:
496
534
groups: ['person']
497
535
denormalizationContext:
498
536
groups: ['person']
499
537
538
+
# The YAML syntax is only supported for Symfony
500
539
# api/config/serializer/Person.yaml
501
540
App\Entity\Person:
502
541
attributes:
@@ -542,6 +581,7 @@ class Person
542
581
```
543
582
544
583
```yaml
584
+
# The YAML syntax is only supported for Symfony
545
585
# api/config/api_platform/resources/Person.yaml
546
586
resources:
547
587
App\Entity\Person:
@@ -555,6 +595,7 @@ properties:
555
595
readableLink: false
556
596
writableLink: false
557
597
598
+
# The YAML syntax is only supported for Symfony
558
599
# api/config/serializer/Person.yaml
559
600
App\Entity\Person:
560
601
attributes:
@@ -566,7 +607,7 @@ App\Entity\Person:
566
607
567
608
</code-selector>
568
609
569
-
### Plain Identifiers
610
+
### Plain Identifiers for Symfony
570
611
571
612
Instead of sending an IRI to set a relation, you may want to send a plain identifier. To do so, you must create your own denormalizer:
572
613
@@ -617,7 +658,7 @@ class PlainIdentifierDenormalizer implements DenormalizerInterface, Denormalizer
617
658
}
618
659
```
619
660
620
-
## Property Normalization Context
661
+
## Property Normalization Context for Symfony
621
662
622
663
If you want to change the (de)normalization context of a property, for instance if you want to change the format of the date time,
623
664
you can do so by using the `#[Context]` attribute from the Symfony Serializer component.
@@ -710,6 +751,9 @@ class Book
710
751
711
752
## Calculated Field
712
753
754
+
> [!NOTE]
755
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
756
+
713
757
Sometimes you need to expose calculated fields. This can be done by leveraging the groups. This time not on a property, but on a method.
714
758
715
759
<code-selector>
@@ -755,13 +799,15 @@ class Greeting
755
799
```
756
800
757
801
```yaml
802
+
# The YAML syntax is only supported for Symfony
758
803
# api/config/api_platform/resources/Greeting.yaml
759
804
App\Entity\Greeting:
760
805
operations:
761
806
ApiPlatform\Metadata\GetCollection:
762
807
normalizationContext:
763
808
groups: 'greeting:collection:get'
764
809
810
+
# The YAML syntax is only supported for Symfony
765
811
# api/config/serializer/Greeting.yaml
766
812
App\Entity\Greeting:
767
813
attributes:
@@ -777,6 +823,9 @@ App\Entity\Greeting:
777
823
778
824
## Changing the Serialization Context Dynamically
779
825
826
+
> [!NOTE]
827
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
828
+
780
829
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform-security/service-decoration?cid=apip"><img src="../symfony/images/symfonycasts-player.png" alt="Context Builder & Service Decoration screencast"><br>Watch the Context Builder & Service Decoration screencast</a></p>
781
830
782
831
Let's imagine a resource where most fields can be managed by any user, but some can be managed only by admin users:
@@ -816,13 +865,15 @@ class Book
816
865
```
817
866
818
867
```yaml
868
+
# The YAML syntax is only supported for Symfony
819
869
# api/config/api_platform/resources/Book.yaml
820
870
App\Entity\Book:
821
871
normalizationContext:
822
872
groups: ['book:output']
823
873
denormalizationContext:
824
874
groups: ['book:input']
825
875
876
+
# The YAML syntax is only supported for Symfony
826
877
# api/config/serializer/Book.yaml
827
878
App\Entity\Book:
828
879
attributes:
@@ -842,6 +893,7 @@ API Platform implements a `ContextBuilder`, which prepares the context for seria
842
893
`createFromRequest` method:
843
894
844
895
```yaml
896
+
# The YAML syntax is only supported for Symfony
845
897
# api/config/services.yaml
846
898
services:
847
899
# ...
@@ -890,7 +942,7 @@ If the user has the `ROLE_ADMIN` permission and the subject is an instance of Bo
890
942
denormalization context. The `$normalization` variable lets you check whether the context is for normalization (if `TRUE`) or denormalization
891
943
(`FALSE`).
892
944
893
-
## Changing the Serialization Context on a Per-item Basis
945
+
## Changing the Serialization Context on a Per-item Basis for Symfony
894
946
895
947
The example above demonstrates how you can modify the normalization/denormalization context based on the current user
896
948
permissions for all books. Sometimes, however, the permissions vary depending on what book is being processed.
@@ -973,7 +1025,7 @@ instance.
973
1025
Note: In this example, we use the `TokenStorageInterface` to verify access to the book instance. However, Symfony
974
1026
provides many useful other services that might be better suited to your use case. For example, the [`AuthorizationChecker`](https://symfony.com/doc/current/components/security/authorization.html#authorization-checker).
975
1027
976
-
## Name Conversion
1028
+
## Name Conversion for Symfony
977
1029
978
1030
The Serializer Component provides a handy way to map PHP field names to serialized names. See the related [Symfony documentation](https://symfony.com/doc/current/components/serializer.html#converting-property-names-when-serializing-and-deserializing).
979
1031
@@ -994,7 +1046,7 @@ api_platform:
994
1046
995
1047
If symfony's `MetadataAwareNameConverter` is available it'll be used by default. If you specify one in ApiPlatform configuration, it'll be used. Note that you can use decoration to benefit from this name converter in your own implementation.
996
1048
997
-
## Decorating a Serializer and Adding Extra Data
1049
+
## Decorating a Serializer and Adding Extra Data for Symfony
998
1050
999
1051
In the following example, we will see how we add extra information to the serialized output. Here is how we add the
1000
1052
date on each request in `GET`:
@@ -1076,8 +1128,15 @@ final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface,
1076
1128
1077
1129
## Entity Identifier Case
1078
1130
1079
-
API Platform is able to guess the entity identifier using Doctrine metadata ([ORM](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/basic-mapping.html#identifiers-primary-keys), [MongoDB ODM](https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/basic-mapping.html#identifiers)).
1080
-
For ORM, it also supports [composite identifiers](https://www.doctrine-project.org/projects/doctrine-orm/en/current/tutorials/composite-primary-keys.html).
1131
+
> [!NOTE]
1132
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
1133
+
1134
+
API Platform is able to guess the entity identifier using Doctrine metadata ([ORM](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/basic-mapping.html#identifiers-primary-keys),
or Laravel Eloquent metadata ([ORM](https://laravel.com/docs/eloquent#primary-keys)).
1137
+
1138
+
For ORM, it also supports [Doctrine composite identifiers](https://www.doctrine-project.org/projects/doctrine-orm/en/current/tutorials/composite-primary-keys.html)
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
1213
+
1150
1214
By default, the generated [JSON-LD context](https://www.w3.org/TR/json-ld/#the-context) (`@context`) is only referenced by
1151
1215
an IRI. A client that uses JSON-LD must send a second HTTP request to retrieve it:
1152
1216
@@ -1180,6 +1244,7 @@ class Book
1180
1244
```
1181
1245
1182
1246
```yaml
1247
+
# The YAML syntax is only supported for Symfony
1183
1248
# api/config/api_platform/resources/Book.yaml
1184
1249
App\Entity\Book:
1185
1250
normalizationContext:
@@ -1207,6 +1272,9 @@ The JSON output will now include the embedded context:
1207
1272
1208
1273
## Collection Relation
1209
1274
1275
+
> [!NOTE]
1276
+
> In Symfony we use the term “entities”, while the following documentation is mostly for Laravel “models”.
1277
+
1210
1278
This is a special case where, in an entity, you have a `toMany` relation. By default, Doctrine will use an `ArrayCollection` to store your values. This is fine when you have a _read_ operation, but when you try to _write_ you can observe an issue where the response is not reflecting the changes correctly. It can lead to client errors even though the update was correct.
1211
1279
Indeed, after an update on this relation, the collection looks wrong because `ArrayCollection`'s indices are not sequential. To change this, we recommend to use a getter that returns `$collectionRelation->getValues()`. Thanks to this, the relation is now a real array which is sequentially indexed.
0 commit comments