Skip to content

Commit 00bc650

Browse files
authored
feat(validation): add section on collecting denormalization errors (#1643)
1 parent 7418c72 commit 00bc650

File tree

2 files changed

+69
-17
lines changed

2 files changed

+69
-17
lines changed

core/configuration.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ api_platform:
6464

6565
# Enable the docs.
6666
enable_docs: true
67-
67+
6868
# Enable the data collector and the WebProfilerBundle integration.
6969
enable_profiler: true
7070

@@ -157,7 +157,7 @@ api_platform:
157157
swagger:
158158
# The active versions of OpenAPI to be exported or used in the swagger_ui. The first value is the default.
159159
versions: [2, 3]
160-
160+
161161
# The swagger API keys.
162162
api_keys: []
163163
# The name of the header or query parameter containing the API key.
@@ -192,7 +192,7 @@ api_platform:
192192
url:
193193

194194
swagger_ui_extra_configuration:
195-
# Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing).
195+
# Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing).
196196
docExpansion: list
197197
# If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown.
198198
filter: false
@@ -375,5 +375,8 @@ api_platform:
375375
# The URL generation strategy to use for IRIs
376376
url_generation_strategy: !php/const ApiPlatform\Api\UrlGeneratorInterface::ABS_PATH
377377

378+
# To enable collecting denormalization errors
379+
collectDenormalizationErrors: false
380+
378381
# ...
379382
```

core/validation.md

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use Symfony\Component\Validator\Constraints as Assert; // Symfony's built-in con
2626
* A product.
2727
*
2828
*/
29-
#[ORM\Entity]
29+
#[ORM\Entity]
3030
#[ApiResource]
3131
class Product
3232
{
@@ -42,7 +42,7 @@ class Product
4242
*
4343
* @MinimalProperties
4444
*/
45-
#[ORM\Column(type: 'json')]
45+
#[ORM\Column(type: 'json')]
4646
public $properties;
4747

4848
// Getters and setters...
@@ -130,10 +130,10 @@ use Symfony\Component\Validator\Constraints as Assert;
130130
#[ApiResource(validationContext: ['groups' => ['a', 'b']])]
131131
class Book
132132
{
133-
#[Assert\NotBlank(groups: ['a'])]
133+
#[Assert\NotBlank(groups: ['a'])]
134134
public string $name;
135135

136-
#[Assert\NotNull(groups: ['b'])]
136+
#[Assert\NotNull(groups: ['b'])]
137137
public string $author;
138138

139139
// ...
@@ -175,15 +175,15 @@ use Symfony\Component\Validator\Constraints as Assert;
175175
#[Post(validationContext: ['groups' => ['Default', 'postValidation']])]
176176
class Book
177177
{
178-
#[Assert\Uuid]
178+
#[Assert\Uuid]
179179
private $id;
180180

181-
#[Assert\NotBlank(groups: ['postValidation'])]
181+
#[Assert\NotBlank(groups: ['postValidation'])]
182182
public $name;
183183

184184
#[Assert\NotNull]
185185
#[Assert\Length(min: 2, max: 50, groups: ['postValidation'])]
186-
#[Assert\Length(min: 2, max: 70, groups: ['putValidation'])]
186+
#[Assert\Length(min: 2, max: 70, groups: ['putValidation'])]
187187
public $author;
188188

189189
// ...
@@ -230,10 +230,10 @@ class Book
230230
return ['a'];
231231
}
232232

233-
#[Assert\NotBlank(groups: ['a'])]
233+
#[Assert\NotBlank(groups: ['a'])]
234234
public $name;
235235

236-
#[Assert\NotNull(groups: ['b'])]
236+
#[Assert\NotNull(groups: ['b'])]
237237
public $author;
238238

239239
// ...
@@ -291,10 +291,10 @@ use Symfony\Component\Validator\Constraints as Assert;
291291
#[ApiResource(validationContext: ['groups' => [AdminGroupsGenerator::class]])
292292
class Book
293293
{
294-
#[Assert\NotBlank(groups: ['a'])]
294+
#[Assert\NotBlank(groups: ['a'])]
295295
public $name;
296296

297-
#[Assert\NotNull(groups: ['b'])]
297+
#[Assert\NotNull(groups: ['b'])]
298298
public $author;
299299

300300
// ...
@@ -354,7 +354,7 @@ class Greeting
354354

355355
/**
356356
* @var A nice person
357-
*
357+
*
358358
* I want this "second" validation to be executed after the "first" one even though I wrote them in this order.
359359
* @One(groups={"second"})
360360
* @Two(groups={"first"})
@@ -523,7 +523,7 @@ Constraints
523523
[`Isbn`](https://symfony.com/doc/current/reference/constraints/Isbn.html) | `https://schema.org/isbn` |
524524
[`Issn`](https://symfony.com/doc/current/reference/constraints/Issn.html) | `https://schema.org/issn` |
525525

526-
## Specification property restrictions
526+
## Specification Property Restrictions
527527

528528
API Platform generates specification property restrictions based on Symfony’s built-in validator.
529529

@@ -555,7 +555,7 @@ final class CustomPropertySchemaRestriction implements PropertySchemaRestriction
555555
return $constraint instanceof CustomConstraint;
556556
}
557557
558-
public function create(Constraint $constraint, ApiProperty $propertyMetadata): array
558+
public function create(Constraint $constraint, ApiProperty $propertyMetadata): array
559559
{
560560
// your logic to create property schema restriction based on constraint
561561
return $restriction;
@@ -573,3 +573,52 @@ services:
573573
'App\PropertySchemaRestriction\CustomPropertySchemaRestriction': ~
574574
# Uncomment only if autoconfiguration is disabled
575575
#tags: [ 'api_platform.metadata.property_schema_restriction' ]
576+
```
577+
578+
## Collecting Denormalization Errors
579+
580+
When submitting data you can collect denormalization errors using the [COLLECT_DENORMALIZATION_ERRORS option](https://symfony.com/doc/current/components/serializer.html#collecting-type-errors-while-denormalizing).
581+
582+
It can be done directly in the `#[ApiResource]` attribute (or in the operations):
583+
584+
```php
585+
<?php
586+
// api/src/Entity/Book.php
587+
namespace App\Entity;
588+
589+
use ApiPlatform\Metadata\ApiResource;
590+
591+
#[ApiResource(
592+
collectDenormalizationErrors: true
593+
)]
594+
class Book
595+
{
596+
public ?bool $boolean;
597+
public ?string $property1;
598+
}
599+
```
600+
601+
If the submitted data has denormalization errors, the HTTP status code will be set to `422 Unprocessable Content` and the response body will contain the list of errors:
602+
603+
```json
604+
{
605+
"@context": "/api/contexts/ConstraintViolationList",
606+
"@type": "ConstraintViolationList",
607+
"hydra:title": "An error occurred",
608+
"hydra:description": "boolean: This value should be of type bool.\nproperty1: This value should be of type string.",
609+
"violations": [
610+
{
611+
"propertyPath": "boolean",
612+
"message": "This value should be of type bool.",
613+
"code": "0"
614+
},
615+
{
616+
"propertyPath": "property1",
617+
"message": "This value should be of type string.",
618+
"code": "0"
619+
}
620+
]
621+
}
622+
```
623+
624+
You can also enable collecting of denormalization errors globally in the [Global Resources Defaults](https://api-platform.com/docs/core/configuration/#global-resources-defaults).

0 commit comments

Comments
 (0)