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 29, 2024
1 parent c278f6c commit 82e9dbc
Show file tree
Hide file tree
Showing 4 changed files with 48 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;

Expand Down Expand Up @@ -1646,10 +1647,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 @@ -2860,6 +2860,17 @@ public function testDiscardChanges()
$this->assertNull($user->getOriginal('name'));
$this->assertNull($user->getAttribute('name'));
}

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
27 changes: 27 additions & 0 deletions tests/Http/JsonResourceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Illuminate\Tests\Http;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Resources\Json\JsonResource;
use Mockery as m;
use PHPUnit\Framework\TestCase;

class JsonResourceTest extends TestCase
{
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 82e9dbc

Please sign in to comment.