bug #27292 [Serializer] Fix and improve constraintViolationListNormalizer's RFC7807 compliance (dunglas)
This PR was squashed before being merged into the 4.1 branch (closes #27292).
Discussion
----------
[Serializer] Fix and improve constraintViolationListNormalizer's RFC7807 compliance
| Q | A
| ------------- | ---
| Branch? | 4.1
| Bug fix? | yes
| New feature? | no <!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks? | no <!-- see https://symfony.com/bc -->
| Deprecations? | yes| Tests pass? | yes <!-- please add some, will be required by reviewers -->
| Fixed tickets | https://github.com/symfony/symfony/pull/22150#discussion_r188674031
| License | MIT
| Doc PR | todo
This PR fixes and improves [RFC 7807](https://tools.ietf.org/html/rfc7807#section-3.2) compliance of `ConstraintViolationListNormalizer` (introduced in 4.1):
* As recommended, use a specific namespace for Symfony validation error (`http://symfony.com/doc/current/validation.html`, because it already exists and gives information about the error.
* Allow to set all properties defined in the RFC using the serialization context
* Remove the `detail` key if no detail is provided (according to the spec)
* Change the Symfony specific extension to use the same terminology than the RFC itself (type and title)
* Use the proper `urn:uuid` scheme (RFC 4122) for the UUID code (more standard, and improve hypermedia capabilities).
ping @teohhanhui
Commits
-------
3c789c610a
[Serializer] Fix and improve constraintViolationListNormalizer's RFC7807 compliance
This commit is contained in:
commit
7fb7cf26ad
@ -32,21 +32,37 @@ class ConstraintViolationListNormalizer implements NormalizerInterface, Cacheabl
|
||||
$violations = array();
|
||||
$messages = array();
|
||||
foreach ($object as $violation) {
|
||||
$violations[] = array(
|
||||
'propertyPath' => $violation->getPropertyPath(),
|
||||
'message' => $violation->getMessage(),
|
||||
'code' => $violation->getCode(),
|
||||
);
|
||||
$propertyPath = $violation->getPropertyPath();
|
||||
|
||||
$violationEntry = array(
|
||||
'propertyPath' => $propertyPath,
|
||||
'title' => $violation->getMessage(),
|
||||
);
|
||||
if (null !== $code = $violation->getCode()) {
|
||||
$violationEntry['type'] = sprintf('urn:uuid:%s', $code);
|
||||
}
|
||||
|
||||
$violations[] = $violationEntry;
|
||||
|
||||
$prefix = $propertyPath ? sprintf('%s: ', $propertyPath) : '';
|
||||
$messages[] = $prefix.$violation->getMessage();
|
||||
}
|
||||
|
||||
return array(
|
||||
'title' => isset($context['title']) ? $context['title'] : 'An error occurred',
|
||||
'detail' => $messages ? implode("\n", $messages) : '',
|
||||
'violations' => $violations,
|
||||
$result = array(
|
||||
'type' => $context['type'] ?? 'https://symfony.com/errors/validation',
|
||||
'title' => $context['title'] ?? 'Validation Failed',
|
||||
);
|
||||
if (isset($context['status'])) {
|
||||
$result['status'] = $context['status'];
|
||||
}
|
||||
if ($messages) {
|
||||
$result['detail'] = implode("\n", $messages);
|
||||
}
|
||||
if (isset($context['instance'])) {
|
||||
$result['instance'] = $context['instance'];
|
||||
}
|
||||
|
||||
return $result + array('violations' => $violations);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,19 +43,20 @@ class ConstraintViolationListNormalizerTest extends TestCase
|
||||
));
|
||||
|
||||
$expected = array(
|
||||
'title' => 'An error occurred',
|
||||
'type' => 'https://symfony.com/errors/validation',
|
||||
'title' => 'Validation Failed',
|
||||
'detail' => 'd: a
|
||||
4: 1',
|
||||
'violations' => array(
|
||||
array(
|
||||
'propertyPath' => 'd',
|
||||
'message' => 'a',
|
||||
'code' => 'f',
|
||||
'title' => 'a',
|
||||
'type' => 'urn:uuid:f',
|
||||
),
|
||||
array(
|
||||
'propertyPath' => '4',
|
||||
'message' => '1',
|
||||
'code' => '6',
|
||||
'title' => '1',
|
||||
'type' => 'urn:uuid:6',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
Reference in New Issue
Block a user