From 1b7a8a5c647b8edb7f887bdc5c14364a601e068e Mon Sep 17 00:00:00 2001 From: Georgi Georgiev Date: Thu, 27 Jun 2024 20:41:58 +0300 Subject: [PATCH] feat: added ignoring of properties (#19) --- README.md | 14 ++++++++++++++ src/Attribute/SerializerContext.php | 1 + src/Denormalizer/ObjectDenormalizer.php | 10 +++++----- src/Metadata/MetadataExtractor.php | 1 + src/Metadata/PropertyMetadata.php | 1 + src/Normalizer/ObjectNormalizer.php | 21 +++++++++------------ tests/Datasets/Person.php | 5 +++++ tests/Unit/IgnoreTest.php | 25 +++++++++++++++++++++++++ 8 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 tests/Unit/IgnoreTest.php diff --git a/README.md b/README.md index 090ec38..f15eb16 100755 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Supports modern PHP projects with fully typed properties. Older codebases with n - [Serialization groups](#serialization-groups) - [Deserialization groups](#deserialization-groups) - [Custom date format](#custom-date-format) + - [Ignore property](#ignore-property) - [Handling of NULL values](#handling-of-null-values) - [Build, run & test locally](#build-run--test-locally) @@ -149,6 +150,19 @@ $serializer = new Serializer( ); ``` +### Ignore property + +Those properties will not be included in the serialized values during serialization and will not be populated with +provided values during deserialization. + +```php +class SomeClass +{ + #[SerializerContext(ignore: true)] + public string $someProperty; +} +``` + ### Handling of NULL values - By default, NULL values are included in the serialized value. diff --git a/src/Attribute/SerializerContext.php b/src/Attribute/SerializerContext.php index 66ecb21..b675c16 100644 --- a/src/Attribute/SerializerContext.php +++ b/src/Attribute/SerializerContext.php @@ -15,6 +15,7 @@ class SerializerContext public function __construct( public ?string $name = null, public ?array $typeMap = null, + public bool $ignore = false, public array $groups = [], public array $attributes = [], ) {} diff --git a/src/Denormalizer/ObjectDenormalizer.php b/src/Denormalizer/ObjectDenormalizer.php index 7b46a5b..b728143 100644 --- a/src/Denormalizer/ObjectDenormalizer.php +++ b/src/Denormalizer/ObjectDenormalizer.php @@ -34,11 +34,11 @@ public function denormalize( $groups = $attributes[SerializerInterface::ATTRIBUTE_GROUPS] ?? null; foreach ($classMetadata->properties as $name => $propertyMetadata) { - if (!array_key_exists($propertyMetadata->serializedName, $data)) { - continue; - } - - if (null !== $groups && [] === array_intersect($groups, $propertyMetadata->groups)) { + if ( + $propertyMetadata->ignore + || !array_key_exists($propertyMetadata->serializedName, $data) + || (null !== $groups && [] === array_intersect($groups, $propertyMetadata->groups)) + ) { continue; } diff --git a/src/Metadata/MetadataExtractor.php b/src/Metadata/MetadataExtractor.php index eae81f3..6ce2df6 100644 --- a/src/Metadata/MetadataExtractor.php +++ b/src/Metadata/MetadataExtractor.php @@ -112,6 +112,7 @@ private function extractPropertyMetadata( attributes: $serializerContext->attributes, readAccess: $this->getPropertyReadAccess($reflectionProperty), writeAccess: $this->getPropertyWriteAccess($reflectionProperty), + ignore: $serializerContext->ignore, ); } diff --git a/src/Metadata/PropertyMetadata.php b/src/Metadata/PropertyMetadata.php index 0759d45..47ef8f6 100644 --- a/src/Metadata/PropertyMetadata.php +++ b/src/Metadata/PropertyMetadata.php @@ -22,6 +22,7 @@ public function __construct( public array $attributes, public ReadAccess $readAccess, public WriteAccess $writeAccess, + public bool $ignore, ) { if (ReadAccess::GETTER == $this->readAccess) { $this->getterMethod = 'get' . ucfirst($this->name); diff --git a/src/Normalizer/ObjectNormalizer.php b/src/Normalizer/ObjectNormalizer.php index cdfbd25..26e8e05 100644 --- a/src/Normalizer/ObjectNormalizer.php +++ b/src/Normalizer/ObjectNormalizer.php @@ -21,21 +21,18 @@ public function normalize(mixed $data, Normalizer $normalizer, array $attributes $groups = $attributes[SerializerInterface::ATTRIBUTE_GROUPS] ?? null; foreach ($classMetadata->properties as $name => $propertyMetadata) { - if (ReadAccess::NONE === $propertyMetadata->readAccess) { + if ( + $propertyMetadata->ignore + || ReadAccess::NONE === $propertyMetadata->readAccess + || (null !== $groups && [] === array_intersect($groups, $propertyMetadata->groups)) + ) { continue; } - if (null !== $groups && [] === array_intersect($groups, $propertyMetadata->groups)) { - continue; - } - - if (ReadAccess::DIRECT === $propertyMetadata->readAccess) { - /** @var scalar|null|object|array $value */ - $value = $data->{$name}; - } else { - /** @var scalar|null|object|array $value */ - $value = $data->{$propertyMetadata->getterMethod}(); - } + /** @var scalar|null|object|array $value */ + $value = (ReadAccess::DIRECT === $propertyMetadata->readAccess) + ? $data->{$name} + : $data->{$propertyMetadata->getterMethod}(); $localAttributes = array_merge($attributes, $propertyMetadata->attributes); diff --git a/tests/Datasets/Person.php b/tests/Datasets/Person.php index c61b008..a029fa7 100644 --- a/tests/Datasets/Person.php +++ b/tests/Datasets/Person.php @@ -4,6 +4,8 @@ namespace Vuryss\Serializer\Tests\Datasets; +use Vuryss\Serializer\Attribute\SerializerContext; + class Person { public string $firstName = 'John'; @@ -12,4 +14,7 @@ class Person public bool $isStudent = true; private string $unUsableProperty = 'unUsableProperty'; + + #[SerializerContext(ignore: true)] + public string $ignoredProperty = 'ignoredProperty'; } diff --git a/tests/Unit/IgnoreTest.php b/tests/Unit/IgnoreTest.php new file mode 100644 index 0000000..5364511 --- /dev/null +++ b/tests/Unit/IgnoreTest.php @@ -0,0 +1,25 @@ +serialize($person); + + expect($json)->toBe('{"firstName":"John","lastName":"Doe","age":25,"isStudent":true}'); +}); + +test('Can ignore properties on deserialization', function () { + $json = '{"firstName":"Jane","lastName":"Bla","age":55,"isStudent":false,"ignoredProperty":"differentValue"}'; + $serializer = new \Vuryss\Serializer\Serializer(); + $person = $serializer->deserialize($json, Person::class); + + expect($person->firstName)->toBe('Jane') + ->and($person->lastName)->toBe('Bla') + ->and($person->age)->toBe(55) + ->and($person->isStudent)->toBe(false) + ->and($person->ignoredProperty)->toBe('ignoredProperty'); +});