From c9be1c78302e76a99f7e7007a6523c6844826ac6 Mon Sep 17 00:00:00 2001 From: Deus Kane Date: Fri, 15 Jul 2022 10:45:49 +0100 Subject: [PATCH] fix: json LD normalizer will now not interfere with operation of other normalizers when useed through the symfony serializer I changed the logic in JsonLdMapNormaliser to stop it trying to (de)normalise things if a different format was specified, because that was interfering with the deserialisation of plain JSON objects. I changed the JsonLdNormaliser as well for consistency, and because I could foresee that allowing it to continue trying to (de)normalise when the format was specified as somthing other than "json-ld" was going to be trouble. --- Client/JsonLDClient.php | 3 +- Serializer/JsonLDMapNormalizer.php | 8 +++++ Serializer/JsonLDNormalizer.php | 14 +++++++- Tests/Serializer/JsonLDMapNormalizerTest.php | 24 +++++++++++++ Tests/Serializer/JsonLDNormalizerTest.php | 37 +++++++++++++++++++- 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/Client/JsonLDClient.php b/Client/JsonLDClient.php index cddb906..95f367a 100644 --- a/Client/JsonLDClient.php +++ b/Client/JsonLDClient.php @@ -346,8 +346,7 @@ protected function makeRequest( $errorResponse = $this->deserialize( $response->getBody()->getContents(), null, - ApiErrorResponse::class, - 'json' + ApiErrorResponse::class ); } catch (JsonLDSerializationException $e2) { } diff --git a/Serializer/JsonLDMapNormalizer.php b/Serializer/JsonLDMapNormalizer.php index a6baf18..e2dcf46 100644 --- a/Serializer/JsonLDMapNormalizer.php +++ b/Serializer/JsonLDMapNormalizer.php @@ -57,11 +57,19 @@ public function normalize($object, $format = null, array $context = []) */ public function supportsDenormalization($data, $type, $format = null, array $context = []): bool { + if (!$this->isCorrectFormat($format, $data)) { + return false; + } + return $this->isDataArray($data); } public function supportsNormalization($data, $format = null, array $context = []) : bool { + if (!$this->isCorrectFormat($format, $data)) { + return false; + } + return $data instanceof ArrayObject; } diff --git a/Serializer/JsonLDNormalizer.php b/Serializer/JsonLDNormalizer.php index 3dbd5ac..ba28453 100644 --- a/Serializer/JsonLDNormalizer.php +++ b/Serializer/JsonLDNormalizer.php @@ -55,8 +55,12 @@ public function normalize($object, $format = null, array $context = []) public function supportsNormalization($data, $format = null, array $context = []) : bool { + if (!$this->isCorrectFormat($format, $data)) { + return false; + } + return ( - (is_object($data) && $format === JsonLDEncoder::FORMAT) + is_object($data) || $this->isDataArray($data) ) && !($data instanceof DateTime) @@ -66,6 +70,10 @@ public function supportsNormalization($data, $format = null, array $context = [] public function supportsDenormalization($data, $type, $format = null, array $context = []) : bool { + if (!$this->isCorrectFormat($format, $data)) { + return false; + } + return isset($data['@type']) || isset($data[0]['@type']) || in_array($type, [ApiErrorResponse::class, ApiError::class. '[]'], true) || @@ -177,4 +185,8 @@ protected function isDataArray($data) : bool { return is_array($data) && (count($data) === 0 || (array_keys($data) === range(0, count($data) - 1))); } + + protected function isCorrectFormat(mixed $format, mixed $data): bool { + return $format === JsonLDEncoder::FORMAT || ($this->isDataArray($data) && $format === null); + } } diff --git a/Tests/Serializer/JsonLDMapNormalizerTest.php b/Tests/Serializer/JsonLDMapNormalizerTest.php index 75978a0..df81389 100644 --- a/Tests/Serializer/JsonLDMapNormalizerTest.php +++ b/Tests/Serializer/JsonLDMapNormalizerTest.php @@ -86,6 +86,30 @@ public function testSupportsMethodReturnsFalseWhenDataIsNotArray(): void $this->assertFalse($jsonLDMapNormalizer->supportsDenormalization(new DateTime(), ''), "types that are not arrays should return false"); } + public function testSupportsMethodReturnsFalseWhenFormatIsNotJsonLD(): void + { + $jsonLDMapNormalizer = new JsonLDMapNormalizer(new ObjectNormalizer(), new MappingCollection([], [])); + + $this->assertFalse($jsonLDMapNormalizer->supportsDenormalization([], '', 'json'), "if format is json should return false"); + $this->assertFalse($jsonLDMapNormalizer->supportsNormalization(new ArrayObject(), 'json'), "if format is json should return false"); + } + + public function testSupportsMethodReturnsTrueWhenFormatIsNull(): void + { + $jsonLDMapNormalizer = new JsonLDMapNormalizer(new ObjectNormalizer(), new MappingCollection([], [])); + + $this->assertTrue($jsonLDMapNormalizer->supportsDenormalization([], ''), "if format is null should support denormalisation"); + $this->assertFalse($jsonLDMapNormalizer->supportsNormalization(new ArrayObject()), "if format is null should not support normalisation of object"); + } + + public function testSupportsMethodReturnsTrueWhenFormatIsJsonLD(): void + { + $jsonLDMapNormalizer = new JsonLDMapNormalizer(new ObjectNormalizer(), new MappingCollection([], [])); + + $this->assertTrue($jsonLDMapNormalizer->supportsDenormalization([], '', 'json-ld'), "if format is json-ld should support denormalisation"); + $this->assertTrue($jsonLDMapNormalizer->supportsNormalization(new ArrayObject(), 'json-ld'), "if format is json-ld should support normalisation"); + } + public function testSupportsMethodReturnsTrueWhenMapValuesHaveTypePropertyDefined(): void { $jsonLDMapNormalizer = new JsonLDMapNormalizer(new ObjectNormalizer(), new MappingCollection([], [])); diff --git a/Tests/Serializer/JsonLDNormalizerTest.php b/Tests/Serializer/JsonLDNormalizerTest.php index 621d2cc..6a576b3 100644 --- a/Tests/Serializer/JsonLDNormalizerTest.php +++ b/Tests/Serializer/JsonLDNormalizerTest.php @@ -6,8 +6,10 @@ use Bookboon\JsonLDClient\Client\JsonLDException; use Bookboon\JsonLDClient\Client\JsonLDSerializationException; use Bookboon\JsonLDClient\Mapping\MappingApi; +use Bookboon\JsonLDClient\Mapping\MappingCollection; use Bookboon\JsonLDClient\Mapping\MappingEndpoint; use Bookboon\JsonLDClient\Serializer\JsonLDEncoder; +use Bookboon\JsonLDClient\Serializer\JsonLDMapNormalizer; use Bookboon\JsonLDClient\Serializer\JsonLDNormalizer; use Bookboon\JsonLDClient\Tests\Fixtures\Models\ChildClass; use Bookboon\JsonLDClient\Tests\Fixtures\Models\CircularChild; @@ -26,6 +28,7 @@ use DateTime; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\NotNormalizableValueException; +use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\SerializerInterface; class JsonLDNormalizerTest extends TestCase @@ -542,6 +545,38 @@ public function testPrefersClassInOwnNamespaceRatherThanMapping(): void $this->assertEquals('childclass', $childClass->getTitle()); } + public function testSupportsMethodReturnsTrueWhenFormatIsNull(): void + { + $jsonLDNormalizer = new JsonLDNormalizer(new ObjectNormalizer(), new MappingCollection([], [])); + + $this->assertTrue($jsonLDNormalizer->supportsDenormalization([ + ['@type' => 'SomeClass'] + ], ''), "if format is null should not support denormalisation of array"); + $this->assertFalse($jsonLDNormalizer->supportsDenormalization( + ['@type' => 'SomeClass'] + , ''), "if format is null should not support denormalisation of object"); + $this->assertTrue($jsonLDNormalizer->supportsNormalization([]), + "if format is null should support normalisation of array"); + $this->assertFalse($jsonLDNormalizer->supportsNormalization(new ArrayObject()), + "if format is null should not support normalisation of object"); + } + + public function testSupportsMethodReturnsTrueWhenFormatIsJsonLd(): void + { + $jsonLDNormalizer = new JsonLDNormalizer(new ObjectNormalizer(), new MappingCollection([], [])); + + $this->assertTrue($jsonLDNormalizer->supportsDenormalization([ + ['@type' => 'SomeClass'] + ], '', 'json-ld'), "if format is json-ld should support denormalisation"); + $this->assertTrue($jsonLDNormalizer->supportsDenormalization( + ['@type' => 'SomeClass'], '', 'json-ld' + ), "if format is json-ld should support denormalisation"); + $this->assertTrue($jsonLDNormalizer->supportsNormalization(new SimpleClass(), 'json-ld'), + "if format is json-ld should support normalisation of object"); + $this->assertTrue($jsonLDNormalizer->supportsNormalization([], 'json-ld'), + "if format is json-ld should support normalisation of array"); + } + private function getContextWithMapping(string $className): array { return [ @@ -549,7 +584,7 @@ private function getContextWithMapping(string $className): array ]; } - private function getSerializerHelper() : SerializerInterface + private function getSerializerHelper(): SerializerInterface { return SerializerHelper::create( [],