Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit68944f5

Browse files
committed
feature#59290 [JsonEncoder] Replace normalizers by value transformers (mtarld)
This PR was merged into the 7.3 branch.Discussion----------[JsonEncoder] Replace normalizers by value transformers| Q | A| ------------- | ---| Branch? | 7.3| Bug fix? | no| New feature? | yes| Deprecations? | no| Issues |Fix#59288| License | MITFor a better DX and to avoid confusion with Serializer's normalizers and denormalizers:1. Merge the `NormalizerInterface` and `DenormalizerInterface` to a single `ValueTransformerInterface`:```phpinterface ValueTransformerInterface{ public function transform(mixed $value, array $options = []): mixed; public static function getJsonValueType(): Type;}```2. Replace the `Normalizer` and `Denormalizer` attributes by a single `ValueTransformer` attribute:```php#[\Attribute(\Attribute::TARGET_PROPERTY)]class ValueTransformer{ // ... public function __construct( callable|string|null $toNativeValue = null, // can be a callable or a ValueTransformerInterface service id callable|string|null $toJsonValue = null, // can be a callable or a ValueTransformerInterface service id ) { // ... } // ...```/cc `@wouterj`Commits-------ced7191 [JsonEncoder] Replace normalizers by value transformers
2 parentsdfd8e53 +ced7191 commit68944f5

File tree

118 files changed

+837
-885
lines changed

Some content is hidden

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

118 files changed

+837
-885
lines changed

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

Lines 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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,10 @@
101101
useSymfony\Component\HttpKernel\DependencyInjection\Extension;
102102
useSymfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
103103
useSymfony\Component\JsonEncoder\Attribute\JsonEncodable;
104-
useSymfony\Component\JsonEncoder\Decode\Denormalizer\DenormalizerInterfaceasJsonEncoderDenormalizerInterface;
105104
useSymfony\Component\JsonEncoder\DecoderInterfaceasJsonEncoderDecoderInterface;
106-
useSymfony\Component\JsonEncoder\Encode\Normalizer\NormalizerInterfaceasJsonEncoderNormalizerInterface;
107105
useSymfony\Component\JsonEncoder\EncoderInterfaceasJsonEncoderEncoderInterface;
108106
useSymfony\Component\JsonEncoder\JsonEncoder;
107+
useSymfony\Component\JsonEncoder\ValueTransformer\ValueTransformerInterface;
109108
useSymfony\Component\Lock\LockFactory;
110109
useSymfony\Component\Lock\LockInterface;
111110
useSymfony\Component\Lock\PersistingStoreInterface;
@@ -2040,10 +2039,8 @@ private function registerJsonEncoderConfiguration(array $config, ContainerBuilde
20402039
thrownewLogicException('JsonEncoder support cannot be enabled as the JsonEncoder component is not installed. Try running "composer require symfony/json-encoder".');
20412040
}
20422041

2043-
$container->registerForAutoconfiguration(JsonEncoderNormalizerInterface::class)
2044-
->addTag('json_encoder.normalizer');
2045-
$container->registerForAutoconfiguration(JsonEncoderDenormalizerInterface::class)
2046-
->addTag('json_encoder.denormalizer');
2042+
$container->registerForAutoconfiguration(ValueTransformerInterface::class)
2043+
->addTag('json_encoder.value_transformer');
20472044

20482045
$loader->load('json_encoder.php');
20492046

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

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
useSymfony\Component\JsonEncoder\CacheWarmer\EncoderDecoderCacheWarmer;
1515
useSymfony\Component\JsonEncoder\CacheWarmer\LazyGhostCacheWarmer;
16-
useSymfony\Component\JsonEncoder\Decode\Denormalizer\DateTimeDenormalizer;
17-
useSymfony\Component\JsonEncoder\Encode\Normalizer\DateTimeNormalizer;
1816
useSymfony\Component\JsonEncoder\JsonDecoder;
1917
useSymfony\Component\JsonEncoder\JsonEncoder;
2018
useSymfony\Component\JsonEncoder\Mapping\Decode\AttributePropertyMetadataLoaderasDecodeAttributePropertyMetadataLoader;
@@ -23,19 +21,21 @@
2321
useSymfony\Component\JsonEncoder\Mapping\Encode\DateTimeTypePropertyMetadataLoaderasEncodeDateTimeTypePropertyMetadataLoader;
2422
useSymfony\Component\JsonEncoder\Mapping\GenericTypePropertyMetadataLoader;
2523
useSymfony\Component\JsonEncoder\Mapping\PropertyMetadataLoader;
24+
useSymfony\Component\JsonEncoder\ValueTransformer\DateTimeToStringValueTransformer;
25+
useSymfony\Component\JsonEncoder\ValueTransformer\StringToDateTimeValueTransformer;
2626

2727
returnstaticfunction (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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111

1212
namespaceSymfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\Dto;
1313

14-
useSymfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeNormalizer;
15-
useSymfony\Component\JsonEncoder\Attribute\Denormalizer;
14+
useSymfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\RangeToStringValueTransformer;
15+
useSymfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder\StringToRangeValueTransformer;
1616
useSymfony\Component\JsonEncoder\Attribute\EncodedName;
1717
useSymfony\Component\JsonEncoder\Attribute\JsonEncodable;
18-
useSymfony\Component\JsonEncoder\Attribute\Normalizer;
18+
useSymfony\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
publicstring$name ='dummy';
3029

31-
#[Normalizer(RangeNormalizer::class)]
32-
#[Denormalizer(RangeNormalizer::class)]
30+
#[ValueTransformer(toJsonValue: RangeToStringValueTransformer::class, toNativeValue: StringToRangeValueTransformer::class)]
3331
publicarray$range = [10,20];
3432
}
Lines 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+
namespaceSymfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder;
13+
14+
useSymfony\Component\JsonEncoder\ValueTransformer\ValueTransformerInterface;
15+
useSymfony\Component\TypeInfo\Type;
16+
useSymfony\Component\TypeInfo\Type\BuiltinType;
17+
18+
/**
19+
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
20+
*/
21+
class RangeToStringValueTransformerimplements ValueTransformerInterface
22+
{
23+
publicfunctiontransform(mixed$value,array$options = []):string
24+
{
25+
return$value[0].'..'.$value[1];
26+
}
27+
28+
publicstaticfunctiongetJsonValueType():BuiltinType
29+
{
30+
return Type::string();
31+
}
32+
}

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

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,21 @@
1111

1212
namespaceSymfony\Bundle\FrameworkBundle\Tests\Functional\app\JsonEncoder;
1313

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

1918
/**
2019
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
2120
*/
22-
classRangeNormalizerimplementsNormalizerInterface, DenormalizerInterface
21+
classStringToRangeValueTransformerimplementsValueTransformerInterface
2322
{
24-
publicfunctionnormalize(mixed$denormalized,array$options = []):string
23+
publicfunctiontransform(mixed$value,array$options = []):array
2524
{
26-
return$denormalized[0].'..'.$denormalized[1];
25+
returnarray_map(staticfn (string$v):int => (int)$v,explode('..',$value));
2726
}
2827

29-
publicfunctiondenormalize(mixed$normalized,array$options = []):array
30-
{
31-
returnarray_map(staticfn (string$v):int => (int)$v,explode('..',$normalized));
32-
}
33-
34-
publicstaticfunctiongetNormalizedType():BuiltinType
28+
publicstaticfunctiongetJsonValueType():BuiltinType
3529
{
3630
return Type::string();
3731
}

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

Lines 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

Lines changed: 0 additions & 43 deletions
This file was deleted.

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

Lines changed: 0 additions & 43 deletions
This file was deleted.
Lines 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+
namespaceSymfony\Component\JsonEncoder\Attribute;
13+
14+
useSymfony\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)|string|null $toNativeValue
32+
* @param (callable(mixed, array<string, mixed>=): mixed)|string|null $toJsonValue
33+
*/
34+
publicfunction__construct(
35+
callable|string|null$toNativeValue =null,
36+
callable|string|null$toJsonValue =null,
37+
) {
38+
if (!$toNativeValue && !$toJsonValue) {
39+
thrownewLogicException('#[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+
publicfunctiongetToNativeValueTransformer():string|\Closure|null
55+
{
56+
return$this->toNativeValue;
57+
}
58+
59+
publicfunctiongetToJsonValueTransformer():string|\Closure|null
60+
{
61+
return$this->toJsonValue;
62+
}
63+
}

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

Lines 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 =newFunctionDataAccessor('get', [newScalarDataAccessor($denormalizer)],newVariableDataAccessor('denormalizers'));
142-
$accessor =newFunctionDataAccessor('denormalize', [$accessor,newVariableDataAccessor('options')],$denormalizerServiceAccessor);
139+
foreach ($propertyMetadata->getToNativeValueTransformers()as$valueTransformer) {
140+
if (\is_string($valueTransformer)) {
141+
$valueTransformerServiceAccessor =newFunctionDataAccessor('get', [newScalarDataAccessor($valueTransformer)],newVariableDataAccessor('valueTransformers'));
142+
$accessor =newFunctionDataAccessor('transform', [$accessor,newVariableDataAccessor('options')],$valueTransformerServiceAccessor);
143143

144144
continue;
145145
}
146146

147147
try {
148-
$functionReflection =new \ReflectionFunction($denormalizer);
148+
$functionReflection =new \ReflectionFunction($valueTransformer);
149149
}catch (\ReflectionException$e) {
150150
thrownewRuntimeException($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,newVariableDataAccessor('options')] : [$accessor];
157157

158158
$accessor =newFunctionDataAccessor($functionName,$arguments);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp