Skip to content

Commit

Permalink
fix(serializer): json violation list normalizer (#5941)
Browse files Browse the repository at this point in the history
* fix(serializer): json violation list normalizer

fixes #5912

* fixes #5916

* fixes #5916
  • Loading branch information
soyuka authored Nov 2, 2023
1 parent 633bde8 commit 436921f
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 1 deletion.
31 changes: 31 additions & 0 deletions features/main/validation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,34 @@ Feature: Using validations groups
]
}
"""

@!mongodb
Scenario: Get violations constraints
When I add "Accept" header equal to "application/json"
And I add "Content-Type" header equal to "application/json"
And I send a "POST" request to "/issue5912s" with body:
"""
{
"title": ""
}
"""
Then the response status code should be 422
And the response should be in JSON
And the JSON should be equal to:
"""
{
"status": 422,
"violations": [
{
"propertyPath": "title",
"message": "This value should not be blank.",
"code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3"
}
],
"detail": "title: This value should not be blank.",
"type": "/validation_errors/c1051bb4-d103-4f74-8988-acbcafc7fdc3",
"title": "An error occurred"
}
"""
And the header "Content-Type" should be equal to "application/problem+json; charset=utf-8"

8 changes: 8 additions & 0 deletions src/Symfony/Bundle/Resources/config/symfony/validator.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@

<tag name="serializer.normalizer" priority="-800" />
</service>

<service id="api_platform.serializer.normalizer.constraint_violation_list" class="ApiPlatform\Symfony\Validator\Serializer\ConstraintViolationListNormalizer" public="false">
<argument>%api_platform.validator.serialize_payload_fields%</argument>
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />

<!-- serializer.normalizer.constraint_violation_list is at 915 -->
<tag name="serializer.normalizer" priority="-900" />
</service>
</services>

</container>
13 changes: 12 additions & 1 deletion src/Symfony/Validator/Exception/ValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
use ApiPlatform\Metadata\Util\CompositeIdentifierParser;
use ApiPlatform\Validator\Exception\ValidationException as BaseValidationException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Validator\ConstraintViolationListInterface;
Expand Down Expand Up @@ -50,7 +51,7 @@
],
graphQlOperations: []
)]
final class ValidationException extends BaseValidationException implements ConstraintViolationListAwareExceptionInterface, \Stringable, ProblemExceptionInterface
final class ValidationException extends BaseValidationException implements ConstraintViolationListAwareExceptionInterface, \Stringable, ProblemExceptionInterface, HttpExceptionInterface
{
private int $status = 422;

Expand Down Expand Up @@ -154,4 +155,14 @@ public function __toString(): string

return $message;
}

public function getStatusCode(): int
{
return $this->status;
}

public function getHeaders(): array
{
return [];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Symfony\Validator\Serializer;

use ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

/**
* Converts {@see \Symfony\Component\Validator\ConstraintViolationListInterface} the API Problem spec (RFC 7807).
*
* @author Kévin Dunglas <[email protected]>
*/
final class ConstraintViolationListNormalizer extends AbstractConstraintViolationListNormalizer
{
public const FORMAT = 'json';

private array $defaultContext = [];

public function __construct(array $serializePayloadFields = null, NameConverterInterface $nameConverter = null, array $defaultContext = [])
{
parent::__construct($serializePayloadFields, $nameConverter);

$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
}

/**
* {@inheritdoc}
*/
public function normalize(mixed $object, string $format = null, array $context = []): array
{
return $this->getViolations($object);
}
}
32 changes: 32 additions & 0 deletions tests/Fixtures/TestBundle/Entity/Issue5912/Dummy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5912;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\NotExposed;
use ApiPlatform\Metadata\Post;
use Symfony\Component\Validator\Constraints\NotBlank;

#[ApiResource(
shortName: 'Issue5912',
operations: [
new NotExposed(),
new Post(),
]
)]
class Dummy
{
#[NotBlank]
public string $title;
}

0 comments on commit 436921f

Please sign in to comment.