8000 [JsonEncoder] Replace normalizers by value transformers · symfony/symfony@ebb3601 · GitHub
[go: up one dir, main page]

Skip to content

Commit ebb3601

Browse files
committed
[JsonEncoder] Replace normalizers by value transformers
1 parent 78f4d9a commit ebb3601

File tree

114 files changed

+796
-909
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+796
-909
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ class UnusedTagsPass implements CompilerPassInterface
5353
'form.type_guesser',
5454
'html_sanitizer',
5555
'http_client.client',
56-
'json_encoder.denormalizer',
5756
'json_encoder.encodable',
58-
'json_encoder.normalizer',
57+
'json_encoder.value_transformer',
5958
'kernel.cache_clearer',
6059
'kernel.cache_warmer',
6160
'kernel.event_listener',

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

+3-6
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,10 @@
9999
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
100100
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
101101
use Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
102-
use Symfony\Component\JsonEncoder\Decode\Denormalizer\DenormalizerInterface as JsonEncoderDenormalizerInterface;
103102
use Symfony\Component\JsonEncoder\DecoderInterface as JsonEncoderDecoderInterface;
104-
use Symfony\Component\JsonEncoder\Encode\Normalizer\NormalizerInterface as JsonEncoderNormalizerInterface;
105103
use Symfony\Component\JsonEncoder\EncoderInterface as JsonEncoderEncoderInterface;
106104
use Symfony\Component\JsonEncoder\JsonEncoder;
105+
use Symfony\Component\JsonEncoder\ValueTransformer\ValueTransformerInterface;
107106
use Symfony\Component\Lock\LockFactory;
108107
use Symfony\Component\Lock\LockInterface;
109108
use Symfony\Component\Lock\PersistingStoreInterface;
@@ -2012,10 +2011,8 @@ private function registerJsonEncoderConfiguration(array $config, ContainerBuilde
20122011
throw new LogicException('JsonEncoder support cannot be enabled as the JsonEncoder component is not installed. Try running "composer require symfony/json-encoder".');
20132012
}
20142013

2015-
$container->registerForAutoconfiguration(JsonEncoderNormalizerInterface::class)
2016-
->addTag('json_encoder.normalizer');
2017-
$container->registerForAutoconfiguration(JsonEncoderDenormalizerInterface::class)
2018-
->addTag('json_encoder.denormalizer');
2014+
$container->registerForAutoconfiguration(ValueTransformerInterface::class)
2015+
->addTag('json_encoder.value_transformer');
20192016

20202017
$loader->load('json_encoder.php');
20212018

src/Symfony/Bundle/FrameworkBundle/Resources/config/json_encoder.php

+10-13
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
use Symfony\Component\JsonEncoder\CacheWarmer\EncoderDecoderCacheWarmer;
1515
use Symfony\Component\JsonEncoder\CacheWarmer\LazyGhostCacheWarmer;
16-
use Symfony\Component\JsonEncoder\Decode\Denormalizer\DateTimeDenormalizer;
17-
use Symfony\Component\JsonEncoder\Encode\Normalizer\DateTimeNormalizer;
1816
use Symfony\Component\JsonEncoder\JsonDecoder;
1917
use Symfony\Component\JsonEncoder\JsonEncoder;
2018
use Symfony\Component\JsonEncoder\Mapping\Decode\AttributePropertyMetadataLoader as DecodeAttributePropertyMetadataLoader;
@@ -23,19 +21,20 @@
2321
use Symfony\Component\JsonEncoder\Mapping\Encode\DateTimeTypePropertyMetadataLoader as EncodeDateTimeTypePropertyMetadataLoader;
2422
use Symfony\Component\JsonEncoder\Mapping\GenericTypePropertyMetadataLoader;
2523
use Symfony\Component\JsonEncoder\Mapping\PropertyMetadataLoader;
24+
use Symfony\Component\JsonEncoder\ValueTransformer\DateTimeValueTransformer;
2625

2726
return static function (ContainerConfigurator $container) {
2827
$container->services()
2928
// encoder/decoder
3029
->set('json_encoder.encoder', JsonEncoder::class)
3130
->args([
32-
tagged_locator('json_encoder.normalizer'),
31+
tagged_locator('json_encoder.value_transformer'),
3332
service('json_encoder.encode.property_metadata_loader'),
3433
param('.json_encoder.encoders_dir'),
3534
])
3635
->set('json_encoder.decoder', JsonDecoder::class)
3736
->args([
38-
tagged_locator('json_encoder.denormalizer'),
37+
tagged_locator('json_encoder.value_transformer'),
3938
service('json_encoder.decode.property_metadata_loader'),
4039
param('.json_encoder.decoders_dir'),
4140
param('.json_encoder.lazy_ghosts_dir'),
@@ -63,7 +62,7 @@
6362
->decorate('json_encoder.encode.property_metadata_loader')
6463
->args([
6564
service('.inner'),
66-
tagged_locator('json_encoder.normalizer'),
65+
tagged_locator('json_encoder.value_transformer'),
6766
service('type_info.resolver'),
6867
])
6968

@@ -86,23 +85,21 @@
8685
->decorate('json_encoder.decode.property_metadata_loader')
8786
->args([
8887
service('.inner'),
89-
tagged_locator('json_encoder.normalizer'),
88+
tagged_locator('json_encoder.value_transformer'),
9089
service('type_info.resolver'),
9190
])
9291

93-
// normalizers/denormalizers
94-
->set('json_encoder.normalizer.date_time', DateTimeNormalizer::class)
95-
->tag('json_encoder.normalizer')
96-
->set('json_encoder.denormalizer.date_time', DateTimeDenormalizer::class)
92+
// value transformers
93+
->set('json_encoder.value_transformer.date_time', DateTimeValueTransformer::class)
9794
->args([
9895
false,
9996
])
100-
->tag('json_encoder.denormalizer')
101-
->set('json_encoder.denormalizer.date_time_immutable', DateTimeDenormalizer::class)
97+
->tag('json_encoder.value_transformer')
98+
->set('json_encoder.value_transformer.date_time_immutable', DateTimeValueTransformer::class)
10299
->args([
103100
true,
104101
])
105-
->tag('json_encoder.denormalizer')
102+
->tag('json_encoder.value_transformer')
106103

107104
// cache
108105
->set('.json_encoder.cache_warmer.encoder_decoder', EncoderDecoderCacheWarmer::class)

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/JsonEncoder/Dto/Dummy.php

+4-7
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,19 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\Dto;
1313

14-
use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeNormalizer;
15-
use Symfony\Component\JsonEncoder\Attribute\Denormalizer;
14+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeValueTransformer;
1615
use Symfony\Component\JsonEncoder\Attribute\EncodedName;
17-
use Symfony\Component\JsonEncoder\Attribute\Normalizer;
16+
use Symfony\Component\JsonEncoder\Attribute\ValueTransformer;
1817

1918
/**
2019
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
2120
*/
2221
class Dummy
2322
{
2423
#[EncodedName('@name')]
25-
#[Normalizer('strtoupper')]
26-
#[Denormalizer('strtolower')]
24+
#[ValueTransformer(toJsonValue: 'strtoupper', toPhpValue: 'strtolower')]
2725
public string $name = 'dummy';
2826

29-
#[Normalizer(RangeNormalizer::class)]
30-
#[Denormalizer(RangeNormalizer::class)]
27+
#[ValueTransformer(RangeValueTransformer::class)]
3128
public array $range = [10, 20];
3229
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/JsonEncoder/RangeNormalizer.php renamed to src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/JsonEncoder/RangeValueTransformer.php

+7-8
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,26 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder;
1313

14-
use Symfony\Component\JsonEncoder\Decode\Denormalizer\DenormalizerInterface;
15-
use Symfony\Component\JsonEncoder\Encode\Normalizer\NormalizerInterface;
14+
use Symfony\Component\JsonEncoder\ValueTransformer\ValueTransformerInterface;
1615
use Symfony\Component\TypeInfo\Type;
1716
use Symfony\Component\TypeInfo\Type\BuiltinType;
1817

1918
/**
2019
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
2120
*/
22-
class RangeNormalizer implements NormalizerInterface, DenormalizerInterface
21+
class RangeValueTransformer implements ValueTransformerInterface
2322
{
24-
public function normalize(mixed $denormalized, array $options = []): string
23+
public function toJsonValue(mixed $phpValue, array $options = []): string
2524
{
26-
return $denormalized[0].'..'.$denormalized[1];
25+
return $phpValue[0].'..'.$phpValue[1];
2726
}
2827

29- 10000
public function denormalize(mixed $normalized, array $options = []): array
28+
public function toPhpValue(mixed $jsonValue, array $options = []): array
3029
{
31-
return array_map(static fn (string $v): int => (int) $v, explode('..', $normalized));
30+
return array_map(static fn (string $v): int => (int) $v, explode('..', $jsonValue));
3231
}
3332

34-
public static function getNormalizedType(): BuiltinType
33+
public static function getJsonValueType(): BuiltinType
3534
{
3635
return Type::string();
3736
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/JsonEncoder/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ services:
2121
alias: json_encoder.decoder
2222
public: true
2323

24-
Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeNormalizer: ~
24+
Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeValueTransformer: ~

src/Symfony/Component/JsonEncoder/Attribute/Denormalizer.php

-43
This file was deleted.

src/Symfony/Component/JsonEncoder/Attribute/Normalizer.php

-43
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\JsonEncoder\Attribute;
13+
14+
use Symfony\Component\JsonEncoder\Exception\LogicException;
15+
16+
/**
17+
* Defines a callable or a {@see \Symfony\Component\JsonEncoder\ValueTransformer\ValueTransformerInterface} service id
18+
* that will be used to transform the property data during encoding and decoding.
19+
*
20+
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
21+
*
22+
* @experimental
23+
*/
24+
#[\Attribute(\Attribute::TARGET_PROPERTY)]
25+
class ValueTransformer
26+
{
27+
private ?\Closure $toPhpValue;
28+
private ?\Closure $toJsonValue;
29+
30+
/**
31+
* @param (callable(mixed, array<string, mixed>?): mixed)|(callable(mixed): mixed)|null $toPhpValue
32+
* @param (callable(mixed, array<string, mixed>?): mixed)|(callable(mixed): mixed)|null $toJsonValue
33+
*/
34+
public function __construct(
35+
private ?string $serviceId = null,
36+
?callable $toPhpValue = null,
37+
?callable $toJsonValue = null,
38+
) {
39+
if (!$serviceId && !($toPhpValue && $toJsonValue)) {
40+
throw new LogicException('#[ValueTransformer] attribute must declare either a $serviceId or $toPhpValue/$toJsonValue callables.');
41+
}
42+
43+
if ($serviceId && ($toPhpValue || $toJsonValue)) {
44+
throw new LogicException('#[ValueTransformer] attribute must declare a $serviceId or $toPhpValue/$toJsonValue callables, but not both.');
45+
}
46+
47+
if ($toPhpValue) {
48+
$this->toPhpValue = \Closure::fromCallable($toPhpValue);
49+
}
50+
51+
if ($toJsonValue) {
52+
$this->toJsonValue = \Closure::fromCallable($toJsonValue);
53+
}
54+
}
55+
56+
public function getToPhpValueTransformer(): string|\Closure|null
57+
{
58+
return $this->toPhpValue ?? $this->serviceId;
59+
}
60+
61+
public function getToJsonValueTransformer(): string|\Closure|null
62+
{
63+
return $this->toJsonValue ?? $this->serviceId;
64+
}
65+
}

src/Symfony/Component/JsonEncoder/Decode/DecoderGenerator.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,16 @@ public function createDataModel(Type $type, array $options = [], array $context
136136
'name' => $propertyMetadata->getName(),
137137
'value' => $this->createDataModel($propertyMetadata->getType(), $options, $context),
138138
'accessor' => function (DataAccessorInterface $accessor) use ($propertyMetadata): DataAccessorInterface {
139-
foreach ($propertyMetadata->getDenormalizers() as $denormalizer) {
140-
if (\is_string($denormalizer)) {
141-
$denormalizerServiceAccessor = new FunctionDataAccessor('get', [new ScalarDataAccessor($denormalizer)], new VariableDataAccessor('denormalizers'));
142-
$accessor = new FunctionDataAccessor('denormalize', [$accessor, new VariableDataAccessor('options')], $denormalizerServiceAccessor);
139+
foreach ($propertyMetadata->getToPhpValueTransformers() as $valueTransformer) {
140+
if (\is_string($valueTransformer)) {
141+
$valueTransformerServiceAccessor = new FunctionDataAccessor('get', [new ScalarDataAccessor($valueTransformer)], new VariableDataAccessor('valueTransformers'));
142+
$accessor = new FunctionDataAccessor('toPhpValue', [$accessor, new VariableDataAccessor('options')], $valueTransformerServiceAccessor);
143143

144144
continue;
145145
}
146146

147147
try {
148-
$functionReflection = new \ReflectionFunction($denormalizer);
148+
$functionReflection = new \ReflectionFunction($valueTransformer);
149149
} catch (\ReflectionException $e) {
150150
throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
151151
}

src/Symfony/Component/JsonEncoder/Decode/Denormalizer/DenormalizerInterface.php

-31
This file was deleted.

0 commit comments

Comments
 (0)
0