.../Core/EventSubscriber/ExceptionJsonSubscriber.php | 11 +++++++++++
core/modules/hal/src/Encoder/JsonEncoder.php | 20 +++-----------------
.../EntityResource/EntityResourceTestBase.php | 18 +++---------------
.../rest/tests/src/Functional/ResourceTestBase.php | 4 +---
.../ResourceResponseSubscriberTest.php | 2 +-
.../serialization/src/Encoder/JsonEncoder.php | 14 ++++++++++++++
6 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
index 2853b98..f9688e9 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
@@ -93,4 +93,15 @@ public function on415(GetResponseForExceptionEvent $event) {
$event->setResponse($response);
}
+ /**
+ * Handles a 422 error for JSON.
+ *
+ * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
+ * The event to process.
+ */
+ public function on422(GetResponseForExceptionEvent $event) {
+ $response = new JsonResponse(['message' => $event->getException()->getMessage()], Response::HTTP_UNPROCESSABLE_ENTITY);
+ $event->setResponse($response);
+ }
+
}
diff --git a/core/modules/hal/src/Encoder/JsonEncoder.php b/core/modules/hal/src/Encoder/JsonEncoder.php
index b722666..bafc487 100644
--- a/core/modules/hal/src/Encoder/JsonEncoder.php
+++ b/core/modules/hal/src/Encoder/JsonEncoder.php
@@ -2,34 +2,20 @@
namespace Drupal\hal\Encoder;
-use Symfony\Component\Serializer\Encoder\JsonEncoder as SymfonyJsonEncoder;
+use Drupal\serialization\Encoder\JsonEncoder as SerializationJsonEncoder;
/**
* Encodes HAL data in JSON.
*
* Simply respond to hal_json format requests using the JSON encoder.
*/
-class JsonEncoder extends SymfonyJsonEncoder {
+class JsonEncoder extends SerializationJsonEncoder {
/**
* The formats that this Encoder supports.
*
* @var string
*/
- protected $format = 'hal_json';
-
- /**
- * {@inheritdoc}
- */
- public function supportsEncoding($format) {
- return $format == $this->format;
- }
-
- /**
- * {@inheritdoc}
- */
- public function supportsDecoding($format) {
- return $format == $this->format;
- }
+ protected static $format = ['hal_json'];
}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index 973f5b9..48ed438 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -565,11 +565,7 @@ public function testPost() {
$response = $this->request('POST', $url, $request_options);
$label_field = $this->entity->getEntityType()->hasKey('label') ? $this->entity->getEntityType()->getKey('label') : static::$labelFieldName;
$label_field_capitalized = ucfirst($label_field);
- // @todo Uncomment, remove next 3 in https://www.drupal.org/node/2813755.
- // $this->assertErrorResponse(422, "Unprocessable Entity: validation failed.\ntitle: Title: this field cannot hold more than 1 values.\n", $response);
- $this->assertSame(422, $response->getStatusCode());
- $this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
- $this->assertSame($this->serializer->encode(['message' => "Unprocessable Entity: validation failed.\n$label_field: $label_field_capitalized: this field cannot hold more than 1 values.\n"], static::$format), (string) $response->getBody());
+ $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\n$label_field: $label_field_capitalized: this field cannot hold more than 1 values.\n", $response);
$request_options[RequestOptions::BODY] = $parseable_invalid_request_body_2;
@@ -577,11 +573,7 @@ public function testPost() {
// DX: 422 when invalid entity: UUID field too long.
$response = $this->request('POST', $url, $request_options);
- // @todo Uncomment, remove next 3 in https://www.drupal.org/node/2813755.
- // $this->assertErrorResponse(422, "Unprocessable Entity: validation failed.\nuuid.0.value: UUID: may not be longer than 128 characters.\n", $response);
- $this->assertSame(422, $response->getStatusCode());
- $this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
- $this->assertSame($this->serializer->encode(['message' => "Unprocessable Entity: validation failed.\nuuid.0.value: UUID: may not be longer than 128 characters.\n"], static::$format), (string) $response->getBody());
+ $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nuuid.0.value: UUID: may not be longer than 128 characters.\n", $response);
$request_options[RequestOptions::BODY] = $parseable_invalid_request_body_3;
@@ -765,11 +757,7 @@ public function testPatch() {
$response = $this->request('PATCH', $url, $request_options);
$label_field = $this->entity->getEntityType()->hasKey('label') ? $this->entity->getEntityType()->getKey('label') : static::$labelFieldName;
$label_field_capitalized = ucfirst($label_field);
- // @todo Uncomment, remove next 3 in https://www.drupal.org/node/2813755.
- // $this->assertErrorResponse(422, "Unprocessable Entity: validation failed.\ntitle: Title: this field cannot hold more than 1 values.\n", $response);
- // $this->assertSame(422, $response->getStatusCode());
- // $this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
- $this->assertSame($this->serializer->encode(['message' => "Unprocessable Entity: validation failed.\n$label_field: $label_field_capitalized: this field cannot hold more than 1 values.\n"], static::$format), (string) $response->getBody());
+ $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\n$label_field: $label_field_capitalized: this field cannot hold more than 1 values.\n", $response);
$request_options[RequestOptions::BODY] = $parseable_invalid_request_body_2;
diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
index f1f0458..49ef8e5 100644
--- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
@@ -340,9 +340,7 @@ protected function assertResourceResponse($expected_status_code, $expected_body,
* The error response to assert.
*/
protected function assertResourceErrorResponse($expected_status_code, $expected_message, ResponseInterface $response) {
- // @todo Fix this in https://www.drupal.org/node/2813755.
- $encode_options = ['json_encode_options' => JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT];
- $expected_body = $this->serializer->encode(['message' => $expected_message], static::$format, $encode_options);
+ $expected_body = $this->serializer->encode(['message' => $expected_message], static::$format);
$this->assertResourceResponse($expected_status_code, $expected_body, $response);
}
diff --git a/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php b/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php
index 87c9059..89770fb 100644
--- a/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php
+++ b/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php
@@ -48,7 +48,7 @@ public function testSerialization($data, $expected_response = FALSE) {
$resource_response_subscriber->onResponse($event);
// Content is a serialized version of the data we provided.
- $this->assertEquals($expected_response !== FALSE ? $expected_response : json_encode($data), $event->getResponse()->getContent());
+ $this->assertEquals($expected_response !== FALSE ? $expected_response : json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT), $event->getResponse()->getContent());
}
public function providerTestSerialization() {
diff --git a/core/modules/serialization/src/Encoder/JsonEncoder.php b/core/modules/serialization/src/Encoder/JsonEncoder.php
index 63e1ddb..18c6066 100644
--- a/core/modules/serialization/src/Encoder/JsonEncoder.php
+++ b/core/modules/serialization/src/Encoder/JsonEncoder.php
@@ -4,6 +4,8 @@
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
+use Symfony\Component\Serializer\Encoder\JsonDecode;
+use Symfony\Component\Serializer\Encoder\JsonEncode;
use Symfony\Component\Serializer\Encoder\JsonEncoder as BaseJsonEncoder;
/**
@@ -21,6 +23,18 @@ class JsonEncoder extends BaseJsonEncoder implements EncoderInterface, DecoderIn
/**
* {@inheritdoc}
*/
+ public function __construct(JsonEncode $encodingImpl = null, JsonDecode $decodingImpl = null) {
+ // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be
+ // embedded into HTML.
+ // @see \Symfony\Component\HttpFoundation\JsonResponse
+ $json_encoding_options = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT;
+ $this->encodingImpl = $encodingImpl ?: new JsonEncode($json_encoding_options);
+ $this->decodingImpl = $decodingImpl ?: new JsonDecode(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function supportsEncoding($format) {
return in_array($format, static::$format);
}