diff --git a/src/Illuminate/Database/Eloquent/Model.php b/src/Illuminate/Database/Eloquent/Model.php index 703b6d4eb086..c6ffbce4e2f1 100644 --- a/src/Illuminate/Database/Eloquent/Model.php +++ b/src/Illuminate/Database/Eloquent/Model.php @@ -20,6 +20,7 @@ use Illuminate\Support\Collection as BaseCollection; use Illuminate\Support\Str; use Illuminate\Support\Traits\ForwardsCalls; +use JsonException; use JsonSerializable; use LogicException; use Stringable; @@ -1656,10 +1657,10 @@ public function toArray() */ public function toJson($options = 0) { - $json = json_encode($this->jsonSerialize(), $options); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw JsonEncodingException::forModel($this, json_last_error_msg()); + try { + $json = json_encode($this->jsonSerialize(), $options | JSON_THROW_ON_ERROR); + } catch (JsonException $e) { + throw JsonEncodingException::forModel($this, $e->getMessage()); } return $json; diff --git a/src/Illuminate/Http/Resources/Json/JsonResource.php b/src/Illuminate/Http/Resources/Json/JsonResource.php index b36a1ab9d605..30b9425b08fb 100644 --- a/src/Illuminate/Http/Resources/Json/JsonResource.php +++ b/src/Illuminate/Http/Resources/Json/JsonResource.php @@ -12,6 +12,7 @@ use Illuminate\Http\Request; use Illuminate\Http\Resources\ConditionallyLoadsAttributes; use Illuminate\Http\Resources\DelegatesToResource; +use JsonException; use JsonSerializable; class JsonResource implements ArrayAccess, JsonSerializable, Responsable, UrlRoutable @@ -144,10 +145,10 @@ public function toArray(Request $request) */ public function toJson($options = 0) { - $json = json_encode($this->jsonSerialize(), $options); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw JsonEncodingException::forResource($this, json_last_error_msg()); + try { + $json = json_encode($this->jsonSerialize(), $options | JSON_THROW_ON_ERROR); + } catch (JsonException $e) { + throw JsonEncodingException::forResource($this, $e->getMessage()); } return $json; diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index 079f68f16747..11757e80384b 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -3037,6 +3037,17 @@ public function testHasAttribute() $this->assertFalse($user->hasAttribute('nonexistent')); $this->assertFalse($user->hasAttribute('belongsToStub')); } + + public function testModelToJsonSucceedsWithPriorErrors(): void + { + $user = new EloquentModelStub(['name' => 'Mateus']); + + // Simulate a JSON error + json_decode('{'); + $this->assertTrue(json_last_error() !== JSON_ERROR_NONE); + + $this->assertSame('{"name":"Mateus"}', $user->toJson(JSON_THROW_ON_ERROR)); + } } class EloquentTestObserverStub diff --git a/tests/Http/JsonResourceTest.php b/tests/Http/JsonResourceTest.php index fcd20c3914d5..8a3a07540618 100644 --- a/tests/Http/JsonResourceTest.php +++ b/tests/Http/JsonResourceTest.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\MissingValue; +use Mockery as m; use PHPUnit\Framework\TestCase; class JsonResourceTest extends TestCase @@ -24,4 +25,20 @@ public function testJsonResourceNullAttributes() $this->assertNull($resource->whenAggregated('relation', 'column', 'sum')); $this->assertNull($resource->whenCounted('relation')); } + + public function testJsonResourceToJsonSucceedsWithPriorErrors(): void + { + $model = new class extends Model {}; + + $resource = m::mock(JsonResource::class, ['resource' => $model]) + ->makePartial() + ->shouldReceive('jsonSerialize')->once()->andReturn(['foo' => 'bar']) + ->getMock(); + + // Simulate a JSON error + json_decode('{'); + $this->assertTrue(json_last_error() !== JSON_ERROR_NONE); + + $this->assertSame('{"foo":"bar"}', $resource->toJson(JSON_THROW_ON_ERROR)); + } }