Skip to content

Commit

Permalink
fix: Model/JsonResource::toJson should not fail with prior json errors (
Browse files Browse the repository at this point in the history
  • Loading branch information
calebdw authored Jul 19, 2024
1 parent 1d36e23 commit 9d7c869
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 8 deletions.
9 changes: 5 additions & 4 deletions src/Illuminate/Database/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 5 additions & 4 deletions src/Illuminate/Http/Resources/Json/JsonResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions tests/Database/DatabaseEloquentModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions tests/Http/JsonResourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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));
}
}

0 comments on commit 9d7c869

Please sign in to comment.