From 050e88990867929b90f4fde1c899b58c26297ffd Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 25 Jun 2015 08:58:19 -0500 Subject: [PATCH 1/2] Serialize without casting. As noted on #63, scalars and nulls can be serialized by PHP, and most (all?) client-side parsers will deserialize them correctly. As such, the more correct route is to pass them verbatim to `json_encode()` instead of casting them to arrays and/or objects. --- doc/book/custom-responses.md | 5 ++--- src/Response/JsonResponse.php | 23 +++++------------------ test/Response/JsonResponseTest.php | 14 ++++---------- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/doc/book/custom-responses.md b/doc/book/custom-responses.md index b2bd8584..8c54e9e1 100644 --- a/doc/book/custom-responses.md +++ b/doc/book/custom-responses.md @@ -52,9 +52,8 @@ the `Content-Type` header to `application/json`: $response = new JsonResponse($data); ``` -If a null value is provide, an empty JSON object is used for the content. Scalar data is cast to an -array before serialization. If providing an object, we recommend implementing -[JsonSerializable](http://php.net/JsonSerializable) to ensure your object is correctly serialized. +If providing an object, we recommend implementing [JsonSerializable](http://php.net/JsonSerializable) +to ensure your object is correctly serialized. Just like the `HtmlResponse`, the `JsonResponse` allows passing two additional arguments — a status code, and an array of headers — to allow you to further seed the initial state of the diff --git a/src/Response/JsonResponse.php b/src/Response/JsonResponse.php index fc508089..ab800cbb 100644 --- a/src/Response/JsonResponse.php +++ b/src/Response/JsonResponse.php @@ -9,27 +9,23 @@ namespace Zend\Diactoros\Response; -use ArrayObject; use InvalidArgumentException; use Zend\Diactoros\Response; use Zend\Diactoros\Stream; /** - * HTML response. + * JSON response. * - * Allows creating a response by passing an HTML string to the constructor; - * by default, sets a status code of 200 and sets the Content-Type header to - * text/html. + * Allows creating a response by passing data to the constructor; by default, + * serializes the data to JSON, sets a status code of 200 and sets the + * Content-Type header to application/json. */ class JsonResponse extends Response { use InjectContentTypeTrait; /** - * Create a JSON response with the given array of data. - * - * If the data provided is null, an empty ArrayObject is used; if the data - * is scalar, it is cast to an array prior to serialization. + * Create a JSON response with the given data. * * Default JSON encoding is performed with the following options, which * produces RFC4627-compliant JSON, capable of embedding into HTML. @@ -69,15 +65,6 @@ private function jsonEncode($data, $encodingOptions) throw new InvalidArgumentException('Cannot JSON encode resources'); } - if ($data === null) { - // Use an ArrayObject to force an empty JSON object. - $data = new ArrayObject(); - } - - if (is_scalar($data)) { - $data = (array) $data; - } - // Clear json_last_error() json_encode(null); diff --git a/test/Response/JsonResponseTest.php b/test/Response/JsonResponseTest.php index 4d24fe87..4bac3a93 100644 --- a/test/Response/JsonResponseTest.php +++ b/test/Response/JsonResponseTest.php @@ -31,17 +31,10 @@ public function testConstructorAcceptsDataAndCreatesJsonEncodedMessageBody() $this->assertSame($json, (string) $response->getBody()); } - public function testNullValuePassedToConstructorRendersEmptyJsonObjectInBody() - { - $response = new JsonResponse(null); - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('application/json', $response->getHeaderLine('content-type')); - $this->assertSame('{}', (string) $response->getBody()); - } - public function scalarValuesForJSON() { return [ + 'null' => [null], 'false' => [false], 'true' => [true], 'zero' => [0], @@ -56,12 +49,13 @@ public function scalarValuesForJSON() /** * @dataProvider scalarValuesForJSON */ - public function testScalarValuePassedToConstructorRendersValueWithinJSONArray($value) + public function testScalarValuePassedToConstructorJsonEncodesDirectly($value) { $response = new JsonResponse($value); $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals('application/json', $response->getHeaderLine('content-type')); - $this->assertSame(json_encode([$value], JSON_UNESCAPED_SLASHES), (string) $response->getBody()); + // 15 is the default mask used by JsonResponse + $this->assertSame(json_encode($value, 15), (string) $response->getBody()); } public function testCanProvideStatusCodeToConstructor() From ea4a197d7cd521b5abdb99305e824f87702f8e42 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 25 Jun 2015 13:07:18 -0500 Subject: [PATCH 2/2] Added CHANGELOG for #64 --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64ecea71..960741ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. -## 1.1.1 - TBD +## 1.1.1 - 2015-06-25 ### Added @@ -18,7 +18,9 @@ All notable changes to this project will be documented in this file, in reverse ### Fixed -- Nothing. +- [#64](https://github.com/zendframework/zend-diactoros/pull/64) fixes the + behavior of `JsonResponse` with regards to serialization of `null` and scalar + values; the new behavior is to serialize them verbatim, without any casting. ## 1.1.0 - 2015-06-24