Skip to content

Commit

Permalink
[5.x] JSON Serialization (#9672)
Browse files Browse the repository at this point in the history
Co-authored-by: jasonvarga <[email protected]>
  • Loading branch information
jasonvarga and jasonvarga authored Apr 12, 2024
1 parent c0dc744 commit 0c078d8
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/Contracts/Data/Augmentable.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Statamic\Contracts\Data;

interface Augmentable
interface Augmentable extends \JsonSerializable
{
public function augmentedValue($key);

Expand Down
10 changes: 9 additions & 1 deletion src/Data/HasAugmentedData.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ public function newAugmentedInstance(): Augmented

public function augmentedArrayData()
{
return method_exists($this, 'values') ? $this->values() : $this->data();
if (method_exists($this, 'values')) {
return $this->values();
}

if (method_exists($this, 'data')) {
return $this->data();
}

throw new \Exception('Augmentable object must have a values() or data() method, or override the augmentedArrayData() method.');
}
}
5 changes: 5 additions & 0 deletions src/Data/HasAugmentedInstance.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public function toArray()
return $this->toEvaluatedAugmentedArray();
}

public function jsonSerialize(): mixed
{
return $this->toArray();
}

public function __get($key)
{
$value = $this->augmentedValue($key);
Expand Down
7 changes: 6 additions & 1 deletion src/Fields/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use JsonSerializable;
use Statamic\Contracts\Data\Augmentable;
use Statamic\Contracts\View\Antlers\Parser;
use Statamic\Facades\Compare;
use Statamic\Support\Str;
use Statamic\View\Antlers\Language\Parser\DocumentTransformer;

Expand Down Expand Up @@ -60,8 +61,12 @@ public function jsonSerialize($options = 0)
{
$value = $this->value();

if (Compare::isQueryBuilder($value)) {
$value = $value->get();
}

if ($value instanceof Augmentable || $value instanceof Collection) {
$value = $value->toAugmentedArray();
$value = $value->toArray();
}

return $value;
Expand Down
4 changes: 0 additions & 4 deletions src/Modifiers/CoreModifiers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2545,10 +2545,6 @@ public function toJson($value, $params)
$value = $value->get();
}

if ($value instanceof Collection || $value instanceof Augmentable) {
$value = $value->toAugmentedArray();
}

return json_encode($value, $options);
}

Expand Down
23 changes: 14 additions & 9 deletions tests/Data/AugmentedCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,15 @@
use Illuminate\Database\Query\Builder as LaravelQueryBuilder;
use JsonSerializable;
use Mockery as m;
use PHPUnit\Framework\TestCase;
use Statamic\Contracts\Data\Augmentable;
use Statamic\Contracts\Query\Builder as StatamicQueryBuilder;
use Statamic\Data\AugmentedCollection;
use Statamic\Data\HasAugmentedData;
use Statamic\Fields\Value;
use Tests\TestCase;

class AugmentedCollectionTest extends TestCase
{
public function tearDown(): void
{
m::close();
}

/** @test */
public function it_calls_toArray_on_each_item()
{
Expand Down Expand Up @@ -147,7 +142,7 @@ public function it_json_serializes()
new TestArrayableObject,
new TestJsonableObject,
new TestJsonSerializeObject,
$augmentable = new TestAugmentableObject,
$augmentable = new TestAugmentableObject(['foo' => 'bar']),
'baz',
$value,
]);
Expand All @@ -156,7 +151,7 @@ public function it_json_serializes()
['foo' => 'bar'],
['foo' => 'bar'],
['foo' => 'bar'],
$augmentable,
['foo' => 'bar'],
'baz',
'value json serialized',
], $c->jsonSerialize());
Expand All @@ -172,7 +167,7 @@ public function augmentables_get_shallow_augmented_when_json_serializing_with_fl
new TestArrayableObject,
new TestJsonableObject,
new TestJsonSerializeObject,
new TestAugmentableObject,
new TestAugmentableObject(['foo' => 'bar']),
'baz',
$value,
]);
Expand Down Expand Up @@ -217,6 +212,16 @@ class TestAugmentableObject implements Augmentable
{
use HasAugmentedData;

public function __construct(private $data)
{

}

public function augmentedArrayData()
{
return $this->data;
}

public function toShallowAugmentedArray()
{
return ['shallow augmented augmentable'];
Expand Down
89 changes: 89 additions & 0 deletions tests/Modifiers/ToJsonTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Modifiers;

use Facades\Tests\Factories\EntryFactory;
use Statamic\Facades\Entry;
use Statamic\Modifiers\Modify;
use Tests\PreventSavingStacheItemsToDisk;
use Tests\TestCase;

class ToJsonTest extends TestCase
{
use PreventSavingStacheItemsToDisk;

/**
* @test
*
* @dataProvider bourneJsonBourneProvider
*/
public function it_converts_to_json($input, $expected): void
{
$modified = $this->modify(value($input));

$this->assertEquals($expected, $modified);
}

/**
* @test
*
* @dataProvider bourneJsonBourneProvider
*/
public function it_pretty_prints($input, $expected): void
{
$modified = $this->modify(value($input), ['pretty']);

$this->assertEquals(json_encode(json_decode($expected, true), JSON_PRETTY_PRINT), $modified);
}

private function modify($value, $options = [])
{
return Modify::value($value)->toJson($options)->fetch();
}

public static function bourneJsonBourneProvider(): array
{
return [
'empty array' => [[], '[]'],
'array' => [['book' => 'All The Places You\'ll Go'], '{"book":"All The Places You\'ll Go"}'],
'string' => ['foo bar baz', '"foo bar baz"'],
'null' => [null, 'null'],
'collection' => [collect(['book' => 'All The Places You\'ll Go']), '{"book":"All The Places You\'ll Go"}'],
'collection with JsonSerializables' => [
collect([
new class implements \JsonSerializable
{
public function jsonSerialize(): array
{
return ['book' => 'All The Places You\'ll Go'];
}
},
new class implements \JsonSerializable
{
public function jsonSerialize(): array
{
return ['book' => 'Oh, The Places You\'ll Go'];
}
},
]), '[{"book":"All The Places You\'ll Go"},{"book":"Oh, The Places You\'ll Go"}]',
],
'JsonSerializable object' => [
new class implements \JsonSerializable
{
public function jsonSerialize(): array
{
return ['book' => 'All The Places You\'ll Go'];
}
}, '{"book":"All The Places You\'ll Go"}',
],
'query builder' => [
function () {
EntryFactory::collection('blog')->data(['title' => 'Post One'])->create();
EntryFactory::collection('blog')->data(['title' => 'Post Two'])->create();

return Entry::query()->get(['title']);
}, '[{"title":"Post One"},{"title":"Post Two"}]',
],
];
}
}

0 comments on commit 0c078d8

Please sign in to comment.