Skip to content

Navigation Menu

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 7f848d9

Browse filesBrowse files
committed
[JsonEncoder] Replace normalizers by value transformers
1 parent 4dcb217 commit 7f848d9
Copy full SHA for 7f848d9

File tree

118 files changed

+831
-880
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

118 files changed

+831
-880
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-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

Copy file name to clipboardExpand all lines: 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;
@@ -2011,10 +2010,8 @@ private function registerJsonEncoderConfiguration(array $config, ContainerBuilde
20112010
throw new LogicException('JsonEncoder support cannot be enabled as the JsonEncoder component is not installed. Try running "composer require symfony/json-encoder".');
20122011
}
20132012

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

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

‎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-19
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-7
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,20 @@
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;
17-
use Symfony\Component\JsonEncoder\Attribute\Normalizer;
17+
use Symfony\Component\JsonEncoder\Attribute\ValueTransformer;
1818

1919
/**
2020
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
2121
*/
2222
class Dummy
2323
{
2424
#[EncodedName('@name')]
25-
#[Normalizer('strtoupper')]
26-
#[Denormalizer('strtolower')]
25+
#[ValueTransformer(toJsonValue: 'strtoupper', toNativeValue: 'strtolower')]
2726
public string $name = 'dummy';
2827

29-
#[Normalizer(RangeNormalizer::class)]
30-
#[Denormalizer(RangeNormalizer::class)]
28+
#[ValueTransformer(toJsonValue: RangeToStringValueTransformer::class, toNativeValue: StringToRangeValueTransformer::class)]
3129
public array $range = [10, 20];
3230
}
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-11
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
+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ services:
1818
alias: json_encoder.decoder
1919
public: true
2020

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

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/JsonEncoder/Attribute/Denormalizer.php
-43
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
-43
This file was deleted.
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/Decode/DecoderGenerator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/JsonEncoder/Decode/DecoderGenerator.php
+7-7
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.