From 6e9764b467e310ff1ea816fc54bcc42f565f7111 Mon Sep 17 00:00:00 2001 From: Ivan Hermanov Date: Sat, 22 Feb 2020 11:34:27 +0200 Subject: [PATCH] Added support of JsonSerializable interface to ArrayableTrait (#17888) --- framework/base/ArrayableTrait.php | 8 ++++-- tests/framework/rest/SerializerTest.php | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/framework/base/ArrayableTrait.php b/framework/base/ArrayableTrait.php index 2da307f..727d71b 100644 --- a/framework/base/ArrayableTrait.php +++ b/framework/base/ArrayableTrait.php @@ -128,12 +128,16 @@ trait ArrayableTrait if ($recursive) { $nestedFields = $this->extractFieldsFor($fields, $field); $nestedExpand = $this->extractFieldsFor($expand, $field); - if ($attribute instanceof Arrayable) { + if ($attribute instanceof \JsonSerializable) { + $attribute = $attribute->jsonSerialize(); + } elseif ($attribute instanceof Arrayable) { $attribute = $attribute->toArray($nestedFields, $nestedExpand); } elseif (is_array($attribute)) { $attribute = array_map( function ($item) use ($nestedFields, $nestedExpand) { - if ($item instanceof Arrayable) { + if ($item instanceof \JsonSerializable) { + return $item->jsonSerialize(); + } elseif ($item instanceof Arrayable) { return $item->toArray($nestedFields, $nestedExpand); } return $item; diff --git a/tests/framework/rest/SerializerTest.php b/tests/framework/rest/SerializerTest.php index fb0334b..6a37643 100644 --- a/tests/framework/rest/SerializerTest.php +++ b/tests/framework/rest/SerializerTest.php @@ -425,6 +425,23 @@ class SerializerTest extends TestCase $this->assertEquals(['customField' => 'test3/test4'], $serializer->serialize($model)); } + + /** + * @see https://github.com/yiisoft/yii2/issues/16334 + */ + public function testSerializeArrayableWithJsonSerializableAttribute() + { + $serializer = new Serializer(); + $model = new TestModel4(); + + $this->assertEquals([ + 'field3' => 'test3', + 'field4' => 'test4', + 'testModel3' => ['customField' => 'test3/test4'], + 'testModelArray' => [['customField' => 'test3/test4']], + ], + $serializer->serialize($model)); + } } class TestModel extends Model @@ -495,3 +512,35 @@ class TestModel3 extends Model implements \JsonSerializable ]; } } + +class TestModel4 extends Model +{ + public static $fields = ['field3', 'field4']; + public static $extraFields = []; + + public $field3 = 'test3'; + public $field4 = 'test4'; + public $extraField4 = 'testExtra2'; + + public function fields() + { + $fields = static::$fields; + $fields['testModel3'] = function() { + return $this->getTestModel3(); + }; + $fields['testModelArray'] = function() { + return [$this->getTestModel3()]; + }; + return $fields; + } + + public function extraFields() + { + return static::$extraFields; + } + + public function getTestModel3() + { + return new TestModel3(); + } +}