Skip to content

Commit f24fb47

Browse files
achrafAaachrafAa2taylorotwell
authored
[12.x] Fix: Add $forceWrap property to JsonResource for consistent API response #56724 (#56736)
* Fix: Add `$forceWrap` property to JsonResource for consistent API response wrapping * code style fixes * remove introduced types to avoid breaking changes * formatting --------- Co-authored-by: achraf <[email protected]> Co-authored-by: Taylor Otwell <[email protected]>
1 parent a308230 commit f24fb47

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

src/Illuminate/Http/Resources/Json/JsonResource.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ class JsonResource implements ArrayAccess, JsonSerializable, Responsable, UrlRou
4949
*/
5050
public static $wrap = 'data';
5151

52+
/**
53+
* Whether to force wrapping even if the $wrap key exists in underlying resource data.
54+
*
55+
* @var bool
56+
*/
57+
public static bool $forceWrapping = false;
58+
5259
/**
5360
* Create a new resource instance.
5461
*

src/Illuminate/Http/Resources/Json/ResourceResponse.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ protected function wrap($data, $with = [], $additional = [])
8080
*/
8181
protected function haveDefaultWrapperAndDataIsUnwrapped($data)
8282
{
83+
if ($this->resource instanceof JsonResource && $this->resource::$forceWrapping) {
84+
return $this->wrapper() !== null;
85+
}
86+
8387
return $this->wrapper() && ! array_key_exists($this->wrapper(), $data);
8488
}
8589

tests/Integration/Http/ResourceTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,61 @@ public function testItThrowsNoErrorInStrictModeWhenResourceIsPaginated()
18531853
}
18541854
}
18551855

1856+
public function testResourceSkipsWrappingWhenDataKeyExists()
1857+
{
1858+
$resource = new class(['id' => 5, 'title' => 'Test', 'data' => 'some data']) extends JsonResource
1859+
{
1860+
public static $wrap = 'data';
1861+
};
1862+
1863+
$response = $resource->toResponse(request());
1864+
$content = json_decode($response->getContent(), true);
1865+
1866+
$this->assertEquals([
1867+
'id' => 5,
1868+
'title' => 'Test',
1869+
'data' => 'some data',
1870+
], $content);
1871+
}
1872+
1873+
public function testResourceWrapsWhenDataKeyDoesNotExist()
1874+
{
1875+
$resource = new class(['id' => 5, 'title' => 'Test']) extends JsonResource
1876+
{
1877+
public static $wrap = 'data';
1878+
};
1879+
1880+
$response = $resource->toResponse(request());
1881+
$content = json_decode($response->getContent(), true);
1882+
1883+
$this->assertEquals([
1884+
'data' => [
1885+
'id' => 5,
1886+
'title' => 'Test',
1887+
],
1888+
], $content);
1889+
}
1890+
1891+
public function testResourceForceWrapOverridesDataKeyCheck()
1892+
{
1893+
$resource = new class(['id' => 5, 'title' => 'Test', 'data' => 'some data']) extends JsonResource
1894+
{
1895+
public static $wrap = 'data';
1896+
public static bool $forceWrapping = true;
1897+
};
1898+
1899+
$response = $resource->toResponse(request());
1900+
$content = json_decode($response->getContent(), true);
1901+
1902+
$this->assertEquals([
1903+
'data' => [
1904+
'id' => 5,
1905+
'title' => 'Test',
1906+
'data' => 'some data',
1907+
],
1908+
], $content);
1909+
}
1910+
18561911
private function assertJsonResourceResponse($data, $expectedJson)
18571912
{
18581913
Route::get('/', function () use ($data) {

0 commit comments

Comments
 (0)