Skip to content

Commit 100f975

Browse files
authored
Fix JSON data response formatter to work well with empty data vs null in data (#20)
1 parent 45151da commit 100f975

File tree

4 files changed

+51
-13
lines changed

4 files changed

+51
-13
lines changed

src/DataResponse.php

+16-11
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ public function getBody(): StreamInterface
3636
return $this->dataStream;
3737
}
3838

39-
if (($response = $this->formatResponse()) !== null) {
40-
$this->response = $response;
39+
if ($this->hasResponseFormatter()) {
40+
$this->response = $this->formatResponse();
4141
return $this->dataStream = $this->response->getBody();
4242
}
4343

@@ -165,17 +165,22 @@ public function getData()
165165
return is_object($this->data) ? clone $this->data : $this->data;
166166
}
167167

168-
private function formatResponse(): ?ResponseInterface
168+
public function hasData(): bool
169169
{
170-
if ($this->responseFormatter !== null) {
171-
$response = $this->responseFormatter->format($this);
172-
if ($response instanceof self) {
173-
throw new \RuntimeException('DataResponseFormatterInterface should not return instance of DataResponse.');
174-
}
170+
return $this->getData() !== null;
171+
}
175172

176-
return $response;
177-
} else {
178-
return null;
173+
/**
174+
* @return ResponseInterface
175+
* @psalm-suppress PossiblyNullReference
176+
*/
177+
private function formatResponse(): ResponseInterface
178+
{
179+
$response = $this->responseFormatter->format($this);
180+
if ($response instanceof self) {
181+
throw new \RuntimeException('DataResponseFormatterInterface should not return instance of DataResponse.');
179182
}
183+
184+
return $response;
180185
}
181186
}

src/Formatter/JsonDataResponseFormatter.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
final class JsonDataResponseFormatter implements DataResponseFormatterInterface
1515
{
1616
use HasContentTypeTrait;
17+
1718
/**
1819
* @var string the Content-Type header for the response
1920
*/
@@ -23,8 +24,12 @@ final class JsonDataResponseFormatter implements DataResponseFormatterInterface
2324

2425
public function format(DataResponse $dataResponse): ResponseInterface
2526
{
27+
$content = '';
2628
$jsonSerializer = new JsonSerializer($this->options);
27-
$content = $jsonSerializer->serialize($dataResponse->getData());
29+
if ($dataResponse->hasData()) {
30+
$content = $jsonSerializer->serialize($dataResponse->getData());
31+
}
32+
2833
$response = $dataResponse->getResponse();
2934
$response->getBody()->write($content);
3035

tests/DataResponseTest.php

+19-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function testSetEmptyResponseFormatter(): void
5959
$dataResponse->getBody()->rewind();
6060

6161
$this->assertTrue($dataResponse->hasResponseFormatter());
62-
$this->assertSame('null', $dataResponse->getBody()->getContents());
62+
$this->assertSame('', $dataResponse->getBody()->getContents());
6363
$this->assertSame(['application/json'], $dataResponse->getHeader('Content-Type'));
6464
}
6565

@@ -203,6 +203,24 @@ public function testGetData(): void
203203
$this->assertEquals('test2', $dataResponse->getData());
204204
}
205205

206+
public function testHasData(): void
207+
{
208+
$dataResponse = $this->createFactory()->createResponse('test');
209+
$dataResponse = $dataResponse->withResponseFormatter(new JsonDataResponseFormatter());
210+
$dataResponse->getBody()->rewind();
211+
212+
$this->assertTrue($dataResponse->hasData());
213+
}
214+
215+
public function testHasDataWithEmptyData(): void
216+
{
217+
$dataResponse = $this->createFactory()->createResponse();
218+
$dataResponse = $dataResponse->withResponseFormatter(new JsonDataResponseFormatter());
219+
$dataResponse->getBody()->rewind();
220+
221+
$this->assertFalse($dataResponse->hasData());
222+
}
223+
206224
private function createFactory(): DataResponseFactory
207225
{
208226
return new DataResponseFactory(new Psr17Factory());

tests/Formatter/JsonDataResponseFormatterTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ public function testWithOptions(): void
4242
$this->assertSame(['application/json'], $result->getHeader(Header::CONTENT_TYPE));
4343
}
4444

45+
public function testWithEmptyResponse(): void
46+
{
47+
$dataResponse = $this->createFactory()->createResponse();
48+
$result = (new JsonDataResponseFormatter())->withOptions(JSON_FORCE_OBJECT)->format($dataResponse);
49+
$result->getBody()->rewind();
50+
51+
$this->assertSame('', $result->getBody()->getContents());
52+
$this->assertSame(['application/json'], $result->getHeader(Header::CONTENT_TYPE));
53+
}
54+
4555
private function createFactory(): DataResponseFactory
4656
{
4757
return new DataResponseFactory(new Psr17Factory());

0 commit comments

Comments
 (0)