Skip to content

Commit 82e9dbc

Browse files
authored
fix: Model/JsonResource::toJson should not fail with prior json errors (#52293)
1 parent c278f6c commit 82e9dbc

File tree

4 files changed

+48
-8
lines changed

4 files changed

+48
-8
lines changed

src/Illuminate/Database/Eloquent/Model.php

Lines changed: 5 additions & 4 deletions
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

@@ -1646,10 +1647,10 @@ public function toArray()
16461647
*/
16471648
public function toJson($options = 0)
16481649
{
1649-
$json = json_encode($this->jsonSerialize(), $options);
1650-
1651-
if (json_last_error() !== JSON_ERROR_NONE) {
1652-
throw JsonEncodingException::forModel($this, json_last_error_msg());
1650+
try {
1651+
$json = json_encode($this->jsonSerialize(), $options | JSON_THROW_ON_ERROR);
1652+
} catch (JsonException $e) {
1653+
throw JsonEncodingException::forModel($this, $e->getMessage());
16531654
}
16541655

16551656
return $json;

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

Lines changed: 5 additions & 4 deletions
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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2860,6 +2860,17 @@ public function testDiscardChanges()
28602860
$this->assertNull($user->getOriginal('name'));
28612861
$this->assertNull($user->getAttribute('name'));
28622862
}
2863+
2864+
public function testModelToJsonSucceedsWithPriorErrors(): void
2865+
{
2866+
$user = new EloquentModelStub(['name' => 'Mateus']);
2867+
2868+
// Simulate a JSON error
2869+
json_decode('{');
2870+
$this->assertTrue(json_last_error() !== JSON_ERROR_NONE);
2871+
2872+
$this->assertSame('{"name":"Mateus"}', $user->toJson(JSON_THROW_ON_ERROR));
2873+
}
28632874
}
28642875

28652876
class EloquentTestObserverStub

tests/Http/JsonResourceTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Http;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Http\Resources\Json\JsonResource;
7+
use Mockery as m;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class JsonResourceTest extends TestCase
11+
{
12+
public function testJsonResourceToJsonSucceedsWithPriorErrors(): void
13+
{
14+
$model = new class extends Model {};
15+
16+
$resource = m::mock(JsonResource::class, ['resource' => $model])
17+
->makePartial()
18+
->shouldReceive('jsonSerialize')->once()->andReturn(['foo' => 'bar'])
19+
->getMock();
20+
21+
// Simulate a JSON error
22+
json_decode('{');
23+
$this->assertTrue(json_last_error() !== JSON_ERROR_NONE);
24+
25+
$this->assertSame('{"foo":"bar"}', $resource->toJson(JSON_THROW_ON_ERROR));
26+
}
27+
}

0 commit comments

Comments
 (0)