From 73c61e7d4cf0a4dabd9a94f72c258a22f086d4bc Mon Sep 17 00:00:00 2001 From: andreaspiening Date: Thu, 19 Apr 2018 15:54:43 +1200 Subject: [PATCH] Cast SilverStripe types to appropriate JSON types (#60) --- src/DataFormatter/JSONDataFormatter.php | 20 +++++++- tests/unit/JSONDataFormatterTest.php | 46 +++++++++++++++++++ tests/unit/JSONDataFormatterTest.yml | 20 ++++++++ .../Stubs/JSONDataFormatterTypeTestObject.php | 32 +++++++++++++ 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 tests/unit/JSONDataFormatterTest.php create mode 100644 tests/unit/JSONDataFormatterTest.yml create mode 100644 tests/unit/Stubs/JSONDataFormatterTypeTestObject.php diff --git a/src/DataFormatter/JSONDataFormatter.php b/src/DataFormatter/JSONDataFormatter.php index b877832..9ae2762 100644 --- a/src/DataFormatter/JSONDataFormatter.php +++ b/src/DataFormatter/JSONDataFormatter.php @@ -9,6 +9,7 @@ use SilverStripe\RestfulServer\DataFormatter; use SilverStripe\ORM\DataObjectInterface; use SilverStripe\Control\Director; use SilverStripe\ORM\SS_List; +use SilverStripe\ORM\FieldType; /** * Formats a DataObject's member fields into a JSON string @@ -89,7 +90,7 @@ class JSONDataFormatter extends DataFormatter continue; } - $fieldValue = $obj->obj($fieldName)->RAW(); + $fieldValue = self::cast($obj->obj($fieldName)); $mappedFieldName = $this->getFieldAlias($className, $fieldName); $serobj->$mappedFieldName = $fieldValue; } @@ -117,7 +118,7 @@ class JSONDataFormatter extends DataFormatter $serobj->$relName = ArrayData::array_to_object(array( "className" => $relClass, "href" => "$href.json", - "id" => $obj->$fieldName + "id" => self::cast($obj->obj($fieldName)) )); } @@ -190,4 +191,19 @@ class JSONDataFormatter extends DataFormatter { return Convert::json2array($strData); } + + public static function cast(FieldType\DBField $dbfield) + { + switch (true) { + case $dbfield instanceof FieldType\DBInt: + return (int)$dbfield->RAW(); + case $dbfield instanceof FieldType\DBFloat: + return (float)$dbfield->RAW(); + case $dbfield instanceof FieldType\DBBoolean: + return (bool)$dbfield->RAW(); + case is_null($dbfield->RAW()): + return null; + } + return $dbfield->RAW(); + } } diff --git a/tests/unit/JSONDataFormatterTest.php b/tests/unit/JSONDataFormatterTest.php new file mode 100644 index 0000000..fe280b5 --- /dev/null +++ b/tests/unit/JSONDataFormatterTest.php @@ -0,0 +1,46 @@ +objFromFixture(JSONDataFormatterTypeTestObject::class, 'parent'); + $json = $formatter->convertDataObject($parent); + $this->assertRegexp('/"ID":\d+/', $json, 'PK casted to integer'); + $this->assertRegexp('/"Created":"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}"/', $json, 'Datetime casted to string'); + $this->assertContains('"Name":"Parent"', $json, 'String casted to string'); + $this->assertContains('"Active":true', $json, 'Boolean casted to boolean'); + $this->assertContains('"Sort":17', $json, 'Integer casted to integer'); + $this->assertContains('"Average":1.2345', $json, 'Float casted to float'); + $this->assertContains('"ParentID":0', $json, 'Empty FK is 0'); + + $child3 = $this->objFromFixture(JSONDataFormatterTypeTestObject::class, 'child3'); + $json = $formatter->convertDataObject($child3); + $this->assertContains('"Name":null', $json, 'Empty string is null'); + $this->assertContains('"Active":false', $json, 'Empty boolean is false'); + $this->assertContains('"Sort":0', $json, 'Empty integer is 0'); + $this->assertContains('"Average":0', $json, 'Empty float is 0'); + $this->assertRegexp('/"ParentID":\d+/', $json, 'FK casted to integer'); + } +} diff --git a/tests/unit/JSONDataFormatterTest.yml b/tests/unit/JSONDataFormatterTest.yml new file mode 100644 index 0000000..4c6f2f8 --- /dev/null +++ b/tests/unit/JSONDataFormatterTest.yml @@ -0,0 +1,20 @@ +SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject: + parent: + Name: Parent + Active: true + Sort: 17 + Average: 1.2345 + child1: + Name: Child 1 + Active: 1 + Sort: 4 + Average: 6.78 + Parent: =>SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject.parent + child2: + Name: Child 2 + Active: false + Sort: 9 + Average: 1 + Parent: =>SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject.parent + child3: + Parent: =>SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject.parent diff --git a/tests/unit/Stubs/JSONDataFormatterTypeTestObject.php b/tests/unit/Stubs/JSONDataFormatterTypeTestObject.php new file mode 100644 index 0000000..99ca52b --- /dev/null +++ b/tests/unit/Stubs/JSONDataFormatterTypeTestObject.php @@ -0,0 +1,32 @@ + 'Varchar', + 'Active' => 'Boolean', + 'Sort' => 'Int', + 'Average' => 'Float', + ]; + + private static $has_one = [ + 'Parent' => JSONDataFormatterTypeTestObject::class, + ]; + + private static $has_many = [ + 'Children' => JSONDataFormatterTypeTestObject::class, + ]; +}