Skip to content

Commit

Permalink
feat: adding serialization groups
Browse files Browse the repository at this point in the history
  • Loading branch information
vuryss committed Jun 24, 2024
1 parent 587515d commit b7893bb
Show file tree
Hide file tree
Showing 15 changed files with 503 additions and 12 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,26 @@ class SomeClass
}
```

### Serialization groups

```php
class SomeClass
{
#[SerializerContext(groups: ['group1'])]
public string $property1;

// Has implicit group 'default'
public string $property2;
}


$serializer = new Serializer();
$object = new SomeClass();
$object->property1 = 'value1';
$object->property2 = 'value2';
$serializer->serialize($object, attributes: [SerializerInterface::ATTRIBUTE_GROUPS => ['group1']]); // {"property1":"value1"}
```

### Custom date format

Per property:
Expand Down
4 changes: 3 additions & 1 deletion src/Attribute/SerializerContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
class SerializerContext
{
/**
* @param array<string, array<string, class-string>> $typeMap
* @param array<string, array<string, class-string>>|null $typeMap
* @param array<string> $groups
* @param array<string, string|int|float|bool> $attributes
*/
public function __construct(
public ?string $name = null,
public ?array $typeMap = null,
public array $groups = [],
public array $attributes = [],
) {}
}
2 changes: 1 addition & 1 deletion src/Denormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{
/**
* @param array<DenormalizerInterface> $denormalizers
* @param array<string, string|int|float|bool> $attributes
* @param array<string, scalar|string[]> $attributes
*/
public function __construct(
private array $denormalizers,
Expand Down
2 changes: 1 addition & 1 deletion src/Metadata/DataType.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class DataType
* @param class-string|null $className
* @param array<DataType> $listType
* @param array<string, array<string, class-string>> $typeMap
* @param array<string, string|int|float|bool> $attributes
* @param array<string, scalar|string[]> $attributes
*/
public function __construct(
public BuiltInType $type,
Expand Down
1 change: 1 addition & 0 deletions src/Metadata/MetadataExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ private function extractPropertyMetadata(
$propertyName,
$serializerContext,
),
groups: [] === $serializerContext->groups ? ['default'] : $serializerContext->groups,
attributes: $serializerContext->attributes,
readAccess: $this->getPropertyReadAccess($reflectionProperty),
writeAccess: $this->getPropertyWriteAccess($reflectionProperty),
Expand Down
2 changes: 2 additions & 0 deletions src/Metadata/PropertyMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ class PropertyMetadata

/**
* @param DataType[] $types
* @param string[] $groups
* @param array<string, string|int|float|bool> $attributes
*/
public function __construct(
public string $name,
public string $serializedName,
public array $types,
public array $groups,
public array $attributes,
public ReadAccess $readAccess,
public WriteAccess $writeAccess,
Expand Down
4 changes: 2 additions & 2 deletions src/Normalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{
/**
* @param array<NormalizerInterface> $normalizers
* @param array<string, string|int|float|bool> $attributes
* @param array<string, scalar|string[]> $attributes
*/
public function __construct(
private array $normalizers,
Expand All @@ -19,7 +19,7 @@ public function __construct(
) {}

/**
* @param array<string, string|int|float|bool> $attributes
* @param array<string, scalar|string[]> $attributes
*
* @throws SerializerException
*/
Expand Down
6 changes: 6 additions & 0 deletions src/Normalizer/ObjectNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ public function normalize(mixed $data, Normalizer $normalizer, array $attributes

$classMetadata = $normalizer->getMetadataExtractor()->extractClassMetadata($data::class);
$normalizedData = [];
/** @var null|string[] $groups */
$groups = $attributes[SerializerInterface::ATTRIBUTE_GROUPS] ?? null;

foreach ($classMetadata->properties as $name => $propertyMetadata) {
if (ReadAccess::NONE === $propertyMetadata->readAccess) {
continue;
}

if (null !== $groups && [] === array_intersect($groups, $propertyMetadata->groups)) {
continue;
}

if (ReadAccess::DIRECT === $propertyMetadata->readAccess) {
/** @var scalar|null|object|array $value */
$value = $data->{$name};
Expand Down
2 changes: 1 addition & 1 deletion src/NormalizerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface NormalizerInterface
/**
* @template T of object|array|scalar|null
*
* @param array<string, string|int|float|bool> $attributes
* @param array<string, scalar|string[]> $attributes
*
* @return T|T[]
* @throws SerializerException
Expand Down
12 changes: 7 additions & 5 deletions src/Serializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Serializer implements SerializerInterface
/**
* @param array<NormalizerInterface> $normalizers
* @param array<DenormalizerInterface> $denormalizers
* @param array<string, string|int|float|bool> $attributes
* @param array<string, scalar|string[]> $attributes
*/
public function __construct(
array $normalizers = [],
Expand Down Expand Up @@ -75,9 +75,9 @@ public function __construct(
);
}

public function serialize(mixed $data): string
public function serialize(mixed $data, array $attributes = []): string
{
$normalizedData = $this->normalize($data);
$normalizedData = $this->normalize($data, $attributes);

try {
return json_encode($normalizedData, JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION);
Expand All @@ -99,11 +99,13 @@ public function deserialize(string $data, ?string $type = null): mixed
}

/**
* @param array<string, scalar|string[]> $attributes
*
* @throws SerializerException
*/
public function normalize(mixed $data): mixed
public function normalize(mixed $data, array $attributes): mixed
{
return $this->normalizer->normalize($data, []);
return $this->normalizer->normalize($data, $attributes);
}

/**
Expand Down
5 changes: 4 additions & 1 deletion src/SerializerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ interface SerializerInterface
{
public const string ATTRIBUTE_DATETIME_FORMAT = 'datetime-format';
public const string ATTRIBUTE_SKIP_NULL_VALUES = 'skip-null-values';
public const string ATTRIBUTE_GROUPS = 'groups';

/**
* Serializes data into a string.
*
* @param array<string, scalar|string[]> $attributes
*
* @throws SerializerException
*/
public function serialize(mixed $data): string;
public function serialize(mixed $data, array $attributes = []): string;

/**
* Deserializes data into the given type.
Expand Down
32 changes: 32 additions & 0 deletions tests/Datasets/Group/SubLevel1.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Vuryss\Serializer\Tests\Datasets\Group;

use Vuryss\Serializer\Attribute\SerializerContext;

class SubLevel1
{
#[SerializerContext(groups: ['group1'])]
public SubLevel2 $nestedPropGroup1;

#[SerializerContext(groups: ['group2'])]
public SubLevel2 $nestedPropGroup2;

#[SerializerContext(groups: ['group1', 'group2'])]
public SubLevel2 $nestedPropGroup1And2;

public SubLevel2 $nestedPropNoGroup;

#[SerializerContext(groups: ['group1'])]
public string $propGroup1;

#[SerializerContext(groups: ['group2'])]
public string $propGroup2;

#[SerializerContext(groups: ['group1', 'group2'])]
public string $propGroup1And2;

public string $propNoGroup;
}
21 changes: 21 additions & 0 deletions tests/Datasets/Group/SubLevel2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Vuryss\Serializer\Tests\Datasets\Group;

use Vuryss\Serializer\Attribute\SerializerContext;

class SubLevel2
{
#[SerializerContext(groups: ['group1'])]
public string $propGroup1;

#[SerializerContext(groups: ['group2'])]
public string $propGroup2;

#[SerializerContext(groups: ['group1', 'group2'])]
public string $propGroup1And2;

public string $propNoGroup;
}
32 changes: 32 additions & 0 deletions tests/Datasets/Group/TopLevelClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Vuryss\Serializer\Tests\Datasets\Group;

use Vuryss\Serializer\Attribute\SerializerContext;

class TopLevelClass
{
#[SerializerContext(groups: ['group1'])]
public SubLevel1 $nestedPropGroup1;

#[SerializerContext(groups: ['group2'])]
public SubLevel1 $nestedPropGroup2;

#[SerializerContext(groups: ['group1', 'group2'])]
public SubLevel1 $nestedPropGroup1And2;

public SubLevel1 $nestedPropNoGroup;

#[SerializerContext(groups: ['group1'])]
public string $propGroup1;

#[SerializerContext(groups: ['group2'])]
public string $propGroup2;

#[SerializerContext(groups: ['group1', 'group2'])]
public string $propGroup1And2;

public string $propNoGroup;
}
Loading

0 comments on commit b7893bb

Please sign in to comment.