Skip to content

Commit 9d7c869

Browse files
authored
fix: Model/JsonResource::toJson should not fail with prior json errors (#52188)
1 parent 1d36e23 commit 9d7c869

File tree

4 files changed

+38
-8
lines changed

4 files changed

+38
-8
lines changed

src/Illuminate/Database/Eloquent/Model.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Illuminate\Support\Collection as BaseCollection;
2121
use Illuminate\Support\Str;
2222
use Illuminate\Support\Traits\ForwardsCalls;
23+
use JsonException;
2324
use JsonSerializable;
2425
use LogicException;
2526
use Stringable;
@@ -1656,10 +1657,10 @@ public function toArray()
16561657
*/
16571658
public function toJson($options = 0)
16581659
{
1659-
$json = json_encode($this->jsonSerialize(), $options);
1660-
1661-
if (json_last_error() !== JSON_ERROR_NONE) {
1662-
throw JsonEncodingException::forModel($this, json_last_error_msg());
1660+
try {
1661+
$json = json_encode($this->jsonSerialize(), $options | JSON_THROW_ON_ERROR);
1662+
} catch (JsonException $e) {
1663+
throw JsonEncodingException::forModel($this, $e->getMessage());
16631664
}
16641665

16651666
return $json;

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Illuminate\Http\Request;
1313
use Illuminate\Http\Resources\ConditionallyLoadsAttributes;
1414
use Illuminate\Http\Resources\DelegatesToResource;
15+
use JsonException;
1516
use JsonSerializable;
1617

1718
class JsonResource implements ArrayAccess, JsonSerializable, Responsable, UrlRoutable
@@ -144,10 +145,10 @@ public function toArray(Request $request)
144145
*/
145146
public function toJson($options = 0)
146147
{
147-
$json = json_encode($this->jsonSerialize(), $options);
148-
149-
if (json_last_error() !== JSON_ERROR_NONE) {
150-
throw JsonEncodingException::forResource($this, json_last_error_msg());
148+
try {
149+
$json = json_encode($this->jsonSerialize(), $options | JSON_THROW_ON_ERROR);
150+
} catch (JsonException $e) {
151+
throw JsonEncodingException::forResource($this, $e->getMessage());
151152
}
152153

153154
return $json;

tests/Database/DatabaseEloquentModelTest.php

+11
Original file line numberDiff line numberDiff line change
@@ -3037,6 +3037,17 @@ public function testHasAttribute()
30373037
$this->assertFalse($user->hasAttribute('nonexistent'));
30383038
$this->assertFalse($user->hasAttribute('belongsToStub'));
30393039
}
3040+
3041+
public function testModelToJsonSucceedsWithPriorErrors(): void
3042+
{
3043+
$user = new EloquentModelStub(['name' => 'Mateus']);
3044+
3045+
// Simulate a JSON error
3046+
json_decode('{');
3047+
$this->assertTrue(json_last_error() !== JSON_ERROR_NONE);
3048+
3049+
$this->assertSame('{"name":"Mateus"}', $user->toJson(JSON_THROW_ON_ERROR));
3050+
}
30403051
}
30413052

30423053
class EloquentTestObserverStub

tests/Http/JsonResourceTest.php

+17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Database\Eloquent\Model;
66
use Illuminate\Http\Resources\Json\JsonResource;
77
use Illuminate\Http\Resources\MissingValue;
8+
use Mockery as m;
89
use PHPUnit\Framework\TestCase;
910

1011
class JsonResourceTest extends TestCase
@@ -24,4 +25,20 @@ public function testJsonResourceNullAttributes()
2425
$this->assertNull($resource->whenAggregated('relation', 'column', 'sum'));
2526
$this->assertNull($resource->whenCounted('relation'));
2627
}
28+
29+
public function testJsonResourceToJsonSucceedsWithPriorErrors(): void
30+
{
31+
$model = new class extends Model {};
32+
33+
$resource = m::mock(JsonResource::class, ['resource' => $model])
34+
->makePartial()
35+
->shouldReceive('jsonSerialize')->once()->andReturn(['foo' => 'bar'])
36+
->getMock();
37+
38+
// Simulate a JSON error
39+
json_decode('{');
40+
$this->assertTrue(json_last_error() !== JSON_ERROR_NONE);
41+
42+
$this->assertSame('{"foo":"bar"}', $resource->toJson(JSON_THROW_ON_ERROR));
43+
}
2744
}

0 commit comments

Comments
 (0)