Last active
January 3, 2019 11:39
-
-
Save rhpaiva/7d08b2bb647e7100a65002327454bcd7 to your computer and use it in GitHub Desktop.
JMS Serializer Visitor Service that does not perform type casting on deserialization.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types = 1); | |
namespace Api\Request; | |
use Api\Request\Exception\DeserializationException; | |
use JMS\Serializer\Context; | |
use JMS\Serializer\Exception\RuntimeException; | |
use JMS\Serializer\GenericDeserializationVisitor; | |
use JMS\Serializer\JsonDeserializationVisitor; | |
use JMS\Serializer\Naming\PropertyNamingStrategyInterface; | |
/** | |
* Reimplements JMS Serializer visitor methods without type casting. | |
* | |
* @package Api\Request | |
*/ | |
class ApiJsonDeserializationVisitor extends GenericDeserializationVisitor | |
{ | |
private $result; | |
/** | |
* @var JsonDeserializationVisitor | |
*/ | |
private $jsonDeserializationVisitor; | |
/** | |
* Overwriting the constructor to be able to pass the original JSON visitor. | |
* | |
* @param PropertyNamingStrategyInterface $namingStrategy | |
* @param JsonDeserializationVisitor $jsonDeserializationVisitor | |
*/ | |
public function __construct( | |
PropertyNamingStrategyInterface $namingStrategy, | |
JsonDeserializationVisitor $jsonDeserializationVisitor | |
) { | |
$this->jsonDeserializationVisitor = $jsonDeserializationVisitor; | |
parent::__construct($namingStrategy); | |
} | |
/** | |
* @param mixed $data | |
* @param array $type | |
* @param Context $context | |
* | |
* @return bool|mixed | |
*/ | |
public function visitBoolean($data, array $type, Context $context) | |
{ | |
return $this->visit($data); | |
} | |
/** | |
* @param mixed $data | |
* @param array $type | |
* @param Context $context | |
* | |
* @return bool|mixed | |
*/ | |
public function visitDouble($data, array $type, Context $context) | |
{ | |
return $this->visit($data); | |
} | |
/** | |
* @param mixed $data | |
* @param array $type | |
* @param Context $context | |
* | |
* @return bool|mixed | |
*/ | |
public function visitInteger($data, array $type, Context $context) | |
{ | |
return $this->visit($data); | |
} | |
/** | |
* @param mixed $data | |
* @param array $type | |
* @param Context $context | |
* | |
* @return bool|mixed | |
*/ | |
public function visitString($data, array $type, Context $context) | |
{ | |
return $this->visit($data); | |
} | |
/** | |
* Proxy to the original decode() from JMS Serializer. | |
* | |
* @param $str | |
* | |
* @return array | |
* @throws DeserializationException When deserialization fails. | |
*/ | |
protected function decode($str) | |
{ | |
try { | |
$decoded = $this->jsonDeserializationVisitor->decode($str); | |
} catch (RuntimeException $e) { | |
throw new DeserializationException($e->getMessage(), $e->getCode(), $e->getPrevious()); | |
} | |
return $decoded; | |
} | |
/** | |
* Reimplementation of visit<Type> from base class. | |
* | |
* @param $data | |
* | |
* @return mixed | |
*/ | |
private function visit($data) | |
{ | |
if ($this->result === null) { | |
$this->result = $data; | |
} | |
return $data; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types = 1); | |
namespace Tests\Unit\Api\Request; | |
use Api\Request\Exception\DeserializationException; | |
use JMS\Serializer\Context; | |
use JMS\Serializer\Exception\RuntimeException; | |
use JMS\Serializer\JsonDeserializationVisitor; | |
use JMS\Serializer\Naming\PropertyNamingStrategyInterface; | |
use Api\Request\ApiJsonDeserializationVisitor; | |
/** | |
* Class ApiJsonDeserializationVisitorTest | |
* @package Tests\Unit\Api\Request | |
*/ | |
class ApiJsonDeserializationVisitorTest extends \PHPUnit_Framework_TestCase | |
{ | |
/** | |
* @var PropertyNamingStrategyInterface | |
*/ | |
private $namingStrategy; | |
/** | |
* @var JsonDeserializationVisitor | |
*/ | |
private $originalJsonVisitor; | |
/** | |
* @var ApiJsonDeserializationVisitor | |
*/ | |
private $apiJsonVisitor; | |
/** | |
* @var Context | |
*/ | |
private $serializationContext; | |
public function setUp() | |
{ | |
$this->namingStrategy = self::createMock(PropertyNamingStrategyInterface::class); | |
$this->originalJsonVisitor = self::createMock(JsonDeserializationVisitor::class); | |
$this->apiJsonVisitor = new ApiJsonDeserializationVisitor( | |
$this->namingStrategy, | |
$this->originalJsonVisitor | |
); | |
$this->serializationContext = self::createMock(Context::class); | |
} | |
/** | |
* @param mixed $data | |
* | |
* @dataProvider providerDeserializationData | |
*/ | |
public function testBooleanVisitorPerformsNoTypeCast($data) | |
{ | |
$visitedData = $this->apiJsonVisitor->visitBoolean($data, [], $this->serializationContext); | |
self::assertEquals($data, $visitedData); | |
} | |
/** | |
* @param mixed $data | |
* | |
* @dataProvider providerDeserializationData | |
*/ | |
public function testDoubleVisitorPerformsNoTypeCast($data) | |
{ | |
$visitedData = $this->apiJsonVisitor->visitDouble($data, [], $this->serializationContext); | |
self::assertEquals($data, $visitedData); | |
} | |
/** | |
* @param mixed $data | |
* | |
* @dataProvider providerDeserializationData | |
*/ | |
public function testIntegerVisitorPerformsNoTypeCast($data) | |
{ | |
$visitedData = $this->apiJsonVisitor->visitInteger($data, [], $this->serializationContext); | |
self::assertEquals($data, $visitedData); | |
} | |
/** | |
* @param mixed $data | |
* | |
* @dataProvider providerDeserializationData | |
*/ | |
public function testStringVisitorPerformsNoTypeCast($data) | |
{ | |
$visitedData = $this->apiJsonVisitor->visitString($data, [], $this->serializationContext); | |
self::assertEquals($data, $visitedData); | |
} | |
/** | |
* @return array | |
*/ | |
public function providerDeserializationData() | |
{ | |
return [ | |
['23edsa'], | |
['asd23edsa'], | |
['asdedsa'], | |
[54.564], | |
[0.00254684], | |
[3565], | |
[false], | |
[true], | |
[0], | |
[1], | |
]; | |
} | |
/** | |
* @covers ApiJsonDeserializationVisitor::decode | |
*/ | |
public function testDeserializationError() | |
{ | |
self::expectException(DeserializationException::class); | |
$this->apiJsonVisitor->prepare('asdsad'); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types = 1); | |
namespace Api\Request\Exception; | |
/** | |
* Exception thrown during a JSON deserialization. | |
* | |
* @package Api\Request\Exception | |
*/ | |
class DeserializationException extends \RuntimeException | |
{ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this goes into your Symfony service definition | |
# overwrites the default json deserializer from JMSSerializer | |
api.request.json_deserialization_visitor: | |
class: Api\Request\ApiJsonDeserializationVisitor | |
decorates: jms_serializer.json_deserialization_visitor | |
decoration_inner_name: jms_serializer.json_deserialization_visitor.original | |
arguments: | |
- '@jms_serializer.cache_naming_strategy' | |
- '@jms_serializer.json_deserialization_visitor.original' | |
tags: | |
- { name: jms_serializer.deserialization_visitor, format: json } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment