Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 507d527

Browse filesBrowse files
committed
[JsonEncoder] Replace normalizers by value transformers
1 parent d4566b2 commit 507d527
Copy full SHA for 507d527

File tree

119 files changed

+838
-885
lines changed
Filter options

Some content is hidden

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

119 files changed

+838
-885
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ class UnusedTagsPass implements CompilerPassInterface
5353
'form.type_guesser',
5454
'html_sanitizer',
5555
'http_client.client',
56-
'json_encoder.denormalizer',
57-
'json_encoder.normalizer',
56+
'json_encoder.value_transformer',
5857
'kernel.cache_clearer',
5958
'kernel.cache_warmer',
6059
'kernel.event_listener',

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+3-6Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,10 @@
101101
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
102102
use Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
103103
use Symfony\Component\JsonEncoder\Attribute\JsonEncodable;
104-
use Symfony\Component\JsonEncoder\Decode\Denormalizer\DenormalizerInterface as JsonEncoderDenormalizerInterface;
105104
use Symfony\Component\JsonEncoder\DecoderInterface as JsonEncoderDecoderInterface;
106-
use Symfony\Component\JsonEncoder\Encode\Normalizer\NormalizerInterface as JsonEncoderNormalizerInterface;
107105
use Symfony\Component\JsonEncoder\EncoderInterface as JsonEncoderEncoderInterface;
108106
use Symfony\Component\JsonEncoder\JsonEncoder;
107+
use Symfony\Component\JsonEncoder\ValueTransformer\ValueTransformerInterface;
109108
use Symfony\Component\Lock\LockFactory;
110109
use Symfony\Component\Lock\LockInterface;
111110
use Symfony\Component\Lock\PersistingStoreInterface;
@@ -2027,10 +2026,8 @@ private function registerJsonEncoderConfiguration(array $config, ContainerBuilde
20272026
throw new LogicException('JsonEncoder support cannot be enabled as the JsonEncoder component is not installed. Try running "composer require symfony/json-encoder".');
20282027
}
20292028

2030-
$container->registerForAutoconfiguration(JsonEncoderNormalizerInterface::class)
2031-
->addTag('json_encoder.normalizer');
2032-
$container->registerForAutoconfiguration(JsonEncoderDenormalizerInterface::class)
2033-
->addTag('json_encoder.denormalizer');
2029+
$container->registerForAutoconfiguration(ValueTransformerInterface::class)
2030+
->addTag('json_encoder.value_transformer');
20342031

20352032
$loader->load('json_encoder.php');
20362033

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/json_encoder.php
+12-19Lines changed: 12 additions & 19 deletions
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,21 @@
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\DateTimeToStringValueTransformer;
25+
use Symfony\Component\JsonEncoder\ValueTransformer\StringToDateTimeValueTransformer;
2626

2727
return static function (ContainerConfigurator $container) {
2828
$container->services()
2929
// encoder/decoder
3030
->set('json_encoder.encoder', JsonEncoder::class)
3131
->args([
32-
tagged_locator('json_encoder.normalizer'),
32+
tagged_locator('json_encoder.value_transformer'),
3333
service('json_encoder.encode.property_metadata_loader'),
3434
param('.json_encoder.encoders_dir'),
3535
])
3636
->set('json_encoder.decoder', JsonDecoder::class)
3737
->args([
38-
tagged_locator('json_encoder.denormalizer'),
38+
tagged_locator('json_encoder.value_transformer'),
3939
service('json_encoder.decode.property_metadata_loader'),
4040
param('.json_encoder.decoders_dir'),
4141
param('.json_encoder.lazy_ghosts_dir'),
@@ -63,7 +63,7 @@
6363
->decorate('json_encoder.encode.property_metadata_loader')
6464
->args([
6565
service('.inner'),
66-
tagged_locator('json_encoder.normalizer'),
66+
tagged_locator('json_encoder.value_transformer'),
6767
service('type_info.resolver'),
6868
])
6969

@@ -86,23 +86,16 @@
8686
->decorate('json_encoder.decode.property_metadata_loader')
8787
->args([
8888
service('.inner'),
89-
tagged_locator('json_encoder.normalizer'),
89+
tagged_locator('json_encoder.value_transformer'),
9090
service('type_info.resolver'),
9191
])
9292

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)
97-
->args([
98-
false,
99-
])
100-
->tag('json_encoder.denormalizer')
101-
->set('json_encoder.denormalizer.date_time_immutable', DateTimeDenormalizer::class)
102-
->args([
103-
true,
104-
])
105-
->tag('json_encoder.denormalizer')
93+
// value transformers
94+
->set('json_encoder.value_transformer.date_time_to_string', DateTimeToStringValueTransformer::class)
95+
->tag('json_encoder.value_transformer')
96+
97+
->set('json_encoder.value_transformer.string_to_date_time', StringToDateTimeValueTransformer::class)
98+
->tag('json_encoder.value_transformer')
10699

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

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/JsonEncoder/Dto/Dummy.php
+5-7Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
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\RangeToStringValueTransformer;
15+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\StringToRangeValueTransformer;
1616
use Symfony\Component\JsonEncoder\Attribute\EncodedName;
1717
use Symfony\Component\JsonEncoder\Attribute\JsonEncodable;
18-
use Symfony\Component\JsonEncoder\Attribute\Normalizer;
18+
use Symfony\Component\JsonEncoder\Attribute\ValueTransformer;
1919

2020
/**
2121
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
@@ -24,11 +24,9 @@
2424
class Dummy
2525
{
2626
#[EncodedName('@name')]
27-
#[Normalizer('strtoupper')]
28-
#[Denormalizer('strtolower')]
27+
#[ValueTransformer(toJsonValue: 'strtoupper', toNativeValue: 'strtolower')]
2928
public string $name = 'dummy';
3029

31-
#[Normalizer(RangeNormalizer::class)]
32-
#[Denormalizer(RangeNormalizer::class)]
30+
#[ValueTransformer(toJsonValue: RangeToStringValueTransformer::class, toNativeValue: StringToRangeValueTransformer::class)]
3331
public array $range = [10, 20];
3432
}
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder;
13+
14+
use Symfony\Component\JsonEncoder\ValueTransformer\ValueTransformerInterface;
15+
use Symfony\Component\TypeInfo\Type;
16+
use Symfony\Component\TypeInfo\Type\BuiltinType;
17+
18+
/**
19+
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
20+
*/
21+
class RangeToStringValueTransformer implements ValueTransformerInterface
22+
{
23+
public function transform(mixed $value, array $options = []): string
24+
{
25+
return $value[0].'..'.$value[1];
26+
}
27+
28+
public static function getJsonValueType(): BuiltinType
29+
{
30+
return Type::string();
31+
}
32+
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/JsonEncoder/StringToRangeValueTransformer.php
+5-11Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,21 @@
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 StringToRangeValueTransformer implements ValueTransformerInterface
2322
{
24-
public function normalize(mixed $denormalized, array $options = []): string
23+
public function transform(mixed $value, array $options = []): array
2524
{
26-
return $denormalized[0].'..'.$denormalized[1];
25+
return array_map(static fn (string $v): int => (int) $v, explode('..', $value));
2726
}
2827

29-
public function denormalize(mixed $normalized, array $options = []): array
30-
{
31-
return array_map(static fn (string $v): int => (int) $v, explode('..', $normalized));
32-
}
33-
34-
public static function getNormalizedType(): BuiltinType
28+
public static function getJsonValueType(): BuiltinType
3529
{
3630
return Type::string();
3731
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/JsonEncoder/config.yml
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ services:
2323
public: true
2424

2525
Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\Dto\Dummy: ~
26-
Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeNormalizer: ~
26+
Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\StringToRangeValueTransformer: ~
27+
Symfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeToStringValueTransformer: ~

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/JsonEncoder/Attribute/Denormalizer.php
-43Lines changed: 0 additions & 43 deletions
This file was deleted.

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/JsonEncoder/Attribute/Normalizer.php
-43Lines changed: 0 additions & 43 deletions
This file was deleted.
+63Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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|string|null $toNativeValue;
28+
private \Closure|string|null $toJsonValue;
29+
30+
/**
31+
* @param (callable(mixed, array<string, mixed>?): mixed)|(callable(mixed): mixed)|string|null $toNativeValue
32+
* @param (callable(mixed, array<string, mixed>?): mixed)|(callable(mixed): mixed)|string|null $toJsonValue
33+
*/
34+
public function __construct(
35+
callable|string|null $toNativeValue = null,
36+
callable|string|null $toJsonValue = null,
37+
) {
38+
if (!$toNativeValue && !$toJsonValue) {
39+
throw new LogicException('#[ValueTransformer] attribute must declare either $toNativeValue or $toJsonValue.');
40+
}
41+
42+
if (\is_callable($toNativeValue)) {
43+
$toNativeValue = $toNativeValue(...);
44+
}
45+
46+
if (\is_callable($toJsonValue)) {
47+
$toJsonValue = $toJsonValue(...);
48+
}
49+
50+
$this->toNativeValue = $toNativeValue;
51+
$this->toJsonValue = $toJsonValue;
52+
}
53+
54+
public function getToNativeValueTransformer(): string|\Closure|null
55+
{
56+
return $this->toNativeValue;
57+
}
58+
59+
public function getToJsonValueTransformer(): string|\Closure|null
60+
{
61+
return $this->toJsonValue;
62+
}
63+
}

‎src/Symfony/Component/JsonEncoder/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/JsonEncoder/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ CHANGELOG
77
* Introduce the component as experimental
88
* Add native PHP lazy ghost support
99
* Allow to select the warmup of object and list in `JsonEncodable` and `json_encoder.encodable`
10+
* Replace normalizers by value transformers

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/JsonEncoder/Decode/DecoderGenerator.php
+7-7Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,23 +136,23 @@ 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->getToNativeValueTransformers() as $valueTransformer) {
140+
if (\is_string($valueTransformer)) {
141+
$valueTransformerServiceAccessor = new FunctionDataAccessor('get', [new ScalarDataAccessor($valueTransformer)], new VariableDataAccessor('valueTransformers'));
142+
$accessor = new FunctionDataAccessor('transform', [$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
}
152152

153-
$functionName = !$functionReflection->getClosureScopeClass()
153+
$functionName = !$functionReflection->getClosureCalledClass()
154154
? $functionReflection->getName()
155-
: \sprintf('%s::%s', $functionReflection->getClosureScopeClass()->getName(), $functionReflection->getName());
155+
: \sprintf('%s::%s', $functionReflection->getClosureCalledClass()->getName(), $functionReflection->getName());
156156
$arguments = $functionReflection->isUserDefined() ? [$accessor, new VariableDataAccessor('options')] : [$accessor];
157157

158158
$accessor = new FunctionDataAccessor($functionName, $arguments);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.