From 18f7970d80ed40ec3da3e4925abdc129c184082b Mon Sep 17 00:00:00 2001 From: Ivan Hermanov Date: Fri, 21 Feb 2020 16:20:29 +0200 Subject: [PATCH] Fix #16334: Serializer support `\JsonSerializable` --- framework/CHANGELOG.md | 1 + framework/rest/Serializer.php | 4 ++- tests/framework/rest/SerializerTest.php | 38 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 5d50319ef5..01e2f6e24e 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.33 under development ------------------------ +- Bug #16334: Serializer support `\JsonSerializable` (germanow) - Bug #17798: Avoid creating folder for stream log targets in `FileTarget` (wapmorgan) - Bug #17850: Update to `ReplaceArrayValue` config exception message (alex-code) - Bug #17843: Fix `yii\web\Session::setCookieParamsInternal` check param "samesite" (schevgeny) diff --git a/framework/rest/Serializer.php b/framework/rest/Serializer.php index 8105eb3697..d63c14b763 100644 --- a/framework/rest/Serializer.php +++ b/framework/rest/Serializer.php @@ -137,7 +137,7 @@ class Serializer extends Component * Serializes the given data into a format that can be easily turned into other formats. * This method mainly converts the objects of recognized types into array representation. * It will not do conversion for unknown object types or non-object data. - * The default implementation will handle [[Model]] and [[DataProviderInterface]]. + * The default implementation will handle [[Model]], [[DataProviderInterface]] and [\JsonSerializable](https://www.php.net/manual/ru/class.jsonserializable.php). * You may override this method to support more object types. * @param mixed $data the data to be serialized. * @return mixed the converted data. @@ -146,6 +146,8 @@ class Serializer extends Component { if ($data instanceof Model && $data->hasErrors()) { return $this->serializeModelErrors($data); + } elseif ($data instanceof \JsonSerializable) { + return $data->jsonSerialize(); } elseif ($data instanceof Arrayable) { return $this->serializeModel($data); } elseif ($data instanceof DataProviderInterface) { diff --git a/tests/framework/rest/SerializerTest.php b/tests/framework/rest/SerializerTest.php index 1bfe7805cc..fb0334bf53 100644 --- a/tests/framework/rest/SerializerTest.php +++ b/tests/framework/rest/SerializerTest.php @@ -414,6 +414,17 @@ class SerializerTest extends TestCase $this->assertEquals($expectedResult, $serializer->serialize($dataProvider)); } + + /** + * @see https://github.com/yiisoft/yii2/issues/16334 + */ + public function testSerializeJsonSerializable() + { + $serializer = new Serializer(); + $model = new TestModel3(); + + $this->assertEquals(['customField' => 'test3/test4'], $serializer->serialize($model)); + } } class TestModel extends Model @@ -457,3 +468,30 @@ class TestModel2 extends Model return static::$extraFields; } } + +class TestModel3 extends Model implements \JsonSerializable +{ + public static $fields = ['field3', 'field4']; + public static $extraFields = []; + + public $field3 = 'test3'; + public $field4 = 'test4'; + public $extraField4 = 'testExtra2'; + + public function fields() + { + return static::$fields; + } + + public function extraFields() + { + return static::$extraFields; + } + + public function jsonSerialize() + { + return [ + 'customField' => $this->field3.'/'.$this->field4, + ]; + } +}