Skip to content

docs: add missing serialization yaml documentation #1370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions core/serialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ level ignored.

In the following example we use different serialization groups for the `GET` and `PUT` operations:

[codeSelector]

```php
<?php
// api/src/Entity/Book.php
Expand Down Expand Up @@ -196,6 +198,29 @@ class Book
}
```

```yaml
# config/api/resources/Book.yaml
App\Entity\Book:
attributes:
normalization_context:
groups: ['get']
itemOperations:
get: ~
put:
normalization_context:
groups: ['put']

# config/serializer/Book.yaml
App\Entity\Book:
attributes:
name:
groups: ['get', 'put']
author:
groups: ['get']
```

[/codeSelector]

The `name` and `author` properties will be included in the document generated during a `GET` operation because the configuration
defined at the resource level is inherited. However the document generated when a `PUT` request will be received will only
include the `name` property because of the specific configuration for this operation.
Expand Down Expand Up @@ -229,6 +254,8 @@ It is possible to embed related objects (in their entirety, or only some of thei
response through the use of serialization groups. By using the following serialization groups annotations (`@Groups`),
a JSON representation of the author is embedded in the book response:

[codeSelector]

```php
<?php
// api/src/Entity/Book.php
Expand Down Expand Up @@ -277,6 +304,30 @@ class Person
}
```

```yaml
# config/api/resources/Book.yaml
App\Entity\Book:
attributes:
normalization_context:
groups: ['book']

# config/serializer/Book.yaml
App\Entity\Book:
attributes:
name:
groups: ['book']
author:
groups: ['book']

# config/serializer/Person.yaml
App\Entity\Person:
attributes:
name:
groups: ['book']
```

[/codeSelector]

The generated JSON using previous settings is below:

```json
Expand Down Expand Up @@ -304,6 +355,8 @@ Instead of embedding relations in the main HTTP response, you may want [to "push
It is also possible to embed a relation in `PUT` and `POST` requests. To enable that feature, set the serialization groups
the same way as normalization. For example:

[codeSelector]

```php
<?php
// api/src/Entity/Book.php
Expand All @@ -319,6 +372,16 @@ class Book
}
```

```yaml
# config/api/resources/Book.yaml
App\Entity\Book:
attributes:
denormalization_context:
groups: ['book']
```

[/codeSelector]

The following rules apply when denormalizing embedded relations:

* If an `@id` key is present in the embedded resource, then the object corresponding to the given URI will be retrieved through
Expand All @@ -331,6 +394,8 @@ You can specify as many embedded relation levels as you want.

It is a common problem to have entities that reference other entities of the same type:

[codeSelector]

```php
<?php
// api/src/Entity/Person.php
Expand Down Expand Up @@ -364,13 +429,34 @@ class Person

// ...
}
```

```yaml
# config/api/resources/Person.yaml
App\Entity\Person:
attributes:
normalization_context:
groups: ['person']
denormalization_context:
groups: ['person']

# config/serializer/Person.yaml
App\Entity\Person:
attributes:
name:
groups: ['person']
parent:
groups: ['person']
```

[/codeSelector]

The problem here is that the **$parent** property become automatically an embedded object. Besides, the property won't be shown on the OpenAPI view.

To force the **$parent** property to be used as an IRI, add an **#[ApiProperty(readableLink: false, writableLink: false)]** annotation:

[codeSelector]

```php
<?php
// api/src/Entity/Person.php
Expand Down Expand Up @@ -408,6 +494,30 @@ class Person

```

```yaml
# config/api/resources/Person.yaml
App\Entity\Person:
attributes:
normalization_context:
groups: ['person']
denormalization_context:
groups: ['person']
properties:
parent:
readableLink: false
writableLink: false

# config/serializer/Person.yaml
App\Entity\Person:
attributes:
name:
groups: ['person']
parent:
groups: ['person']
```

[/codeSelector]

## Property Normalization Context

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,
Expand Down Expand Up @@ -521,6 +631,8 @@ class Book

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.

[codeSelector]

```php
<?php

Expand Down Expand Up @@ -579,12 +691,35 @@ class Greeting
}
```

```yaml
# config/api/resources/Greeting.yaml
App\Entity\Greeting:
collectionOperations:
get:
normalization_context:
groups: 'greeting:collection:get'

# config/serializer/Greeting.yaml
App\Entity\Greeting:
attributes:
id:
groups: 'greeting:collection:get'
name:
groups: 'greeting:collection:get'
getSum:
groups: 'greeting:collection:get'
```

[/codeSelector]

## Changing the Serialization Context Dynamically

<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform-security/service-decoration?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="Context Builder & Service Decoration screencast"><br>Watch the Context Builder & Service Decoration screencast</a></p>

Let's imagine a resource where most fields can be managed by any user, but some can be managed only by admin users:

[codeSelector]

```php
<?php
// api/src/Entity/Book.php
Expand Down Expand Up @@ -624,6 +759,26 @@ class Book
}
```

```yaml
# config/api/resources/Book.yaml
App\Entity\Book:
attributes:
normalization_context:
groups: ['book:output']
denormalization_context:
groups: ['book:input']

# config/serializer/Book.yaml
App\Entity\Book:
attributes:
active:
groups: ['book:output', 'admin:input']
name:
groups: ['book:output', 'book:input']
```

[/codeSelector]

All entry points are the same for all users, so we should find a way to detect if the authenticated user is an admin, and if so
dynamically add the `admin:input` value to deserialization groups in the `$context` array.

Expand Down Expand Up @@ -939,6 +1094,8 @@ an IRI. A client that uses JSON-LD must send a second HTTP request to retrieve i
You can configure API Platform to embed the JSON-LD context in the root document by adding the `jsonld_embed_context`
attribute to the `#[ApiResource]` annotation:

[codeSelector]

```php
<?php
// api/src/Entity/Book.php
Expand All @@ -954,6 +1111,16 @@ class Book
}
```

```yaml
# config/api/resources/Book.yaml
App\Entity\Book:
attributes:
normalization_context:
jsonld_embed_context: true
```

[/codeSelector]

The JSON output will now include the embedded context:

```json
Expand Down