@@ -389,6 +389,341 @@ the specific configuration for this operation.
389389
390390Refer to the [operations](operations.md) documentation to learn more.
391391
392+ # # Using Serialization Attributes
393+
394+ In addition to using serialization groups, you can specify which attributes (properties) of a
395+ resource should be exposed during normalization (read) and denormalization (write) processes. This
396+ is done through the `attributes` key in the serialization context.
397+
398+ It is simple to specify which attributes to use in the API system :
399+
400+ 1. Add the normalization context and denormalization context to the resource, and specify which
401+ attributes to expose.
402+ 2. You can specify nested attributes for related objects using array syntax.
403+
404+ <code-selector>
405+
406+ ` ` ` php
407+ <?php
408+ // api/src/ApiResource/Book.php with Symfony or app/ApiResource/Book.php with Laravel
409+ namespace App\A piResource;
410+
411+ use ApiPlatform\M etadata\A piResource;
412+
413+ #[ApiResource(
414+ normalizationContext: [
415+ 'attributes' => ['id', 'title', 'author' => ['name']],
416+ ],
417+ denormalizationContext: [
418+ 'attributes' => ['title', 'author' => ['name']],
419+ ],
420+ )]
421+ class Book
422+ {
423+ public ?int $id = null;
424+
425+ public string $title = '';
426+
427+ public Author $author;
428+
429+ public string $isbn = '';
430+
431+ // ...
432+ }
433+ ` ` `
434+
435+ ` ` ` yaml
436+ # The YAML syntax is only supported for Symfony
437+ # api/config/api_platform/resources/Book.yaml
438+ App\A piResource\B ook:
439+ normalizationContext:
440+ attributes: ['id', 'title', 'author' => ['name']]
441+ denormalizationContext:
442+ attributes: ['title', 'author' => ['name']]
443+ ` ` `
444+
445+ ` ` ` xml
446+ <!-- The XML syntax is only supported for Symfony -->
447+ <!-- api/config/api_platform/resources.xml -->
448+ <?xml version="1.0" encoding="UTF-8" ?>
449+ <resources xmlns="https://api-platform.com/schema/metadata/resources-3.0"
450+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
451+ xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
452+ https://api-platform.com/schema/metadata/resources-3.0.xsd">
453+ <resource class="App\A piResource\B ook">
454+ <normalizationContext>
455+ <values>
456+ <value name="attributes">
457+ <values>
458+ <value>id</value>
459+ <value>title</value>
460+ <value key="author">
461+ <values>
462+ <value>name</value>
463+ </values>
464+ </value>
465+ </values>
466+ </value>
467+ </values>
468+ </normalizationContext>
469+ <denormalizationContext>
470+ <values>
471+ <value name="attributes">
472+ <values>
473+ <value>title</value>
474+ <value key="author">
475+ <values>
476+ <value>name</value>
477+ </values>
478+ </value>
479+ </values>
480+ </value>
481+ </values>
482+ </denormalizationContext>
483+ </resource>
484+ </resources>
485+ ` ` `
486+
487+ </code-selector>
488+
489+ <code-selector>
490+
491+ ` ` ` php
492+ <?php
493+ // api/src/ApiResource/Author.php with Symfony or app/ApiResource/Author.php with Laravel
494+ namespace App\A piResource;
495+
496+ use ApiPlatform\M etadata\A piResource;
497+
498+ #[ApiResource]
499+ class Author
500+ {
501+ public ?int $id = null;
502+
503+ public string $name;
504+
505+ // ...
506+ }
507+ ` ` `
508+
509+ ` ` ` yaml
510+ # The YAML syntax is only supported for Symfony
511+ # api/config/api_platform/resources/Author.yaml
512+ App\A piResource\A uthor: ~
513+ ` ` `
514+
515+ ` ` ` xml
516+ <!-- The XML syntax is only supported for Symfony -->
517+ <!-- api/config/api_platform/resources.xml -->
518+ <?xml version="1.0" encoding="UTF-8" ?>
519+ <resources xmlns="https://api-platform.com/schema/metadata/resources-3.0"
520+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
521+ xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
522+ https://api-platform.com/schema/metadata/resources-3.0.xsd">
523+ <resource class="App\A piResource\A uthor" />
524+ </resources>
525+ ` ` `
526+
527+ </code-selector>
528+
529+ In the previous example, the `id`, `title` properties and the nested `author.name` will be visible
530+ when reading (`GET`) the object. When writing (`PUT` / `PATCH` / `POST`), only `title` and
531+ ` author.name` are accepted. The `isbn` property is never exposed because it was not specified in the
532+ attributes list.
533+
534+ Internally, API Platform passes the value of the `normalizationContext` as the 3rd argument of
535+ [the `Serializer::serialize()` method](https://api.symfony.com/master/Symfony/Component/Serializer/SerializerInterface.html#method_serialize)
536+ during the normalization process. `denormalizationContext` is passed as the 4th argument of
537+ [the `Serializer::deserialize()` method](https://api.symfony.com/master/Symfony/Component/Serializer/SerializerInterface.html#method_deserialize)
538+ during denormalization (writing).
539+
540+ In addition to the `attributes` key, you can configure any Symfony Serializer option through the
541+ ` $context` parameter (e.g. the `enable_max_depth` key when using
542+ [the `@MaxDepth` annotation](https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth)).
543+
544+ Any attributes configuration that you specify will also be leveraged by the built-in actions and the
545+ OpenAPI documentation generator.
546+
547+ # # Using Serialization Attributes per Operation
548+
549+ It is possible to specify normalization and denormalization contexts (as well as any other
550+ attribute) on a per-operation basis. API Platform will always use the most specific definition. For
551+ instance, if normalization attributes are set both at the resource level and at the operation level,
552+ the configuration set at the operation level will be used and the resource level ignored.
553+
554+ In the following example we use different attributes for the `GET` and `POST` operations :
555+
556+ <code-selector>
557+
558+ ` ` ` php
559+ <?php
560+ // api/src/ApiResource/Book.php with Symfony or app/ApiResource/Book.php with Laravel
561+ namespace App\A piResource;
562+
563+ use ApiPlatform\M etadata\A piResource;
564+ use ApiPlatform\M etadata\G et;
565+ use ApiPlatform\M etadata\P ost;
566+
567+ #[ApiResource]
568+ #[Get(
569+ normalizationContext: [
570+ 'attributes' => ['id', 'title', 'author' => ['name']],
571+ ],
572+ )]
573+ #[Post(
574+ denormalizationContext: [
575+ 'attributes' => ['title', 'name', 'author' => ['name']],
576+ ],
577+ normalizationContext: [
578+ 'attributes' => ['id', 'title', 'author' => ['id', 'name']],
579+ ],
580+ )]
581+ class Book
582+ {
583+ public ?int $id = null;
584+
585+ public string $title = 'The book title';
586+
587+ public ?string $name = null;
588+
589+ public Author $author;
590+
591+ public string $isbn = '978-3-16-148410-0';
592+
593+ // ...
594+ }
595+ ` ` `
596+
597+ ` ` ` yaml
598+ # The YAML syntax is only supported for Symfony
599+ # api/config/api_platform/resources/Book.yaml
600+ App\A piResource\B ook:
601+ operations:
602+ ApiPlatform\M etadata\G et:
603+ normalizationContext:
604+ attributes: ['id', 'title', 'author' => ['name']]
605+ ApiPlatform\M etadata\P ost:
606+ denormalizationContext:
607+ attributes: ['title', 'name', 'author' => ['name']]
608+ normalizationContext:
609+ attributes: ['id', 'title', 'author' => ['id', 'name']]
610+ ` ` `
611+
612+ ` ` ` xml
613+ <!-- The XML syntax is only supported for Symfony -->
614+ <!-- api/config/api_platform/resources.xml -->
615+ <?xml version="1.0" encoding="UTF-8" ?>
616+ <resources xmlns="https://api-platform.com/schema/metadata/resources-3.0"
617+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
618+ xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
619+ https://api-platform.com/schema/metadata/resources-3.0.xsd">
620+ <resource class="App\A piResource\B ook">
621+ <operations>
622+ <operation class="ApiPlatform\M etadata\G et">
623+ <normalizationContext>
624+ <values>
625+ <value name="attributes">
626+ <values>
627+ <value>id</value>
628+ <value>title</value>
629+ <value key="author">
630+ <values>
631+ <value>name</value>
632+ </values>
633+ </value>
634+ </values>
635+ </value>
636+ </values>
637+ </normalizationContext>
638+ </operation>
639+ <operation class="ApiPlatform\M etadata\P ost">
640+ <denormalizationContext>
641+ <values>
642+ <value name="attributes">
643+ <values>
644+ <value>title</value>
645+ <value>name</value>
646+ <value key="author">
647+ <values>
648+ <value>name</value>
649+ </values>
650+ </value>
651+ </values>
652+ </value>
653+ </values>
654+ </denormalizationContext>
655+ <normalizationContext>
656+ <values>
657+ <value name="attributes">
658+ <values>
659+ <value>id</value>
660+ <value>title</value>
661+ <value key="author">
662+ <values>
663+ <value>id</value>
664+ <value>name</value>
665+ </values>
666+ </value>
667+ </values>
668+ </value>
669+ </values>
670+ </normalizationContext>
671+ </operation>
672+ </operations>
673+ </resource>
674+ </resources>
675+ ` ` `
676+
677+ </code-selector>
678+
679+ <code-selector>
680+
681+ ` ` ` php
682+ <?php
683+ // api/src/ApiResource/Author.php with Symfony or app/ApiResource/Author.php with Laravel
684+ namespace App\A piResource;
685+
686+ use ApiPlatform\M etadata\A piResource;
687+
688+ #[ApiResource]
689+ class Author
690+ {
691+ public ?int $id = null;
692+
693+ public string $name;
694+
695+ // ...
696+ }
697+ ` ` `
698+
699+ ` ` ` yaml
700+ # The YAML syntax is only supported for Symfony
701+ # api/config/api_platform/resources/Author.yaml
702+ App\A piResource\A uthor: ~
703+ ` ` `
704+
705+ ` ` ` xml
706+ <!-- The XML syntax is only supported for Symfony -->
707+ <!-- api/config/api_platform/resources.xml -->
708+ <?xml version="1.0" encoding="UTF-8" ?>
709+ <resources xmlns="https://api-platform.com/schema/metadata/resources-3.0"
710+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
711+ xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
712+ https://api-platform.com/schema/metadata/resources-3.0.xsd">
713+ <resource class="App\A piResource\A uthor" />
714+ </resources>
715+ ` ` `
716+
717+ </code-selector>
718+
719+ The `id`, `title` and `author.name` attributes will be included in the document generated during a
720+ ` GET` operation because the operation-specific configuration is used. However the document generated
721+ when a `POST` request will be received will only include `id`, `title`, and `author` with `id` and
722+ ` name` in the response because of the specific configuration for this operation. The `POST` request
723+ input accepts `title`, `name`, and `author.name`.
724+
725+ Refer to the [operations](operations.md) documentation to learn more.
726+
392727# # Embedding Relations
393728
394729<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>
0 commit comments