Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.6k
Description
Description
Introduction
We already have the functionality to denormalize objects from different parts of data via#[SerializedPath('[some][path]')]
and with different names via#[SerializedName('different_name)]
.
For example,
Let's imagine we have classFoo
with the next structure:
class Foo{publicfunction__construct( #[SerializedPath('[internal][property]')]publicstring$bar, #[SerializedName('outter')]publicstring$some ) { }}
and we have the next data to denormalize:
$data = ['internal' => ['property' =>'value1', ],'outter' =>'value2',]
When we denormalize$data
via$serializer
we will get the object with desirable values:
//useSymfony\Component\Serializer\Encoder\JsonEncoder;useSymfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;useSymfony\Component\Serializer\Normalizer\ObjectNormalizer;useSymfony\Component\Serializer\Serializer;$classMetadataFactory =newClassMetadataFactory(newAnnotationLoader(newAnnotationReader()));$metadataAwareNameConverter =newMetadataAwareNameConverter($classMetadataFactory);$serializer =newSerializer( [newObjectNormalizer($classMetadataFactory,$metadataAwareNameConverter)], ['json' =>newJsonEncoder()]);$object =$serializer->denormalize($data, Foo::class);$object->bar;// 'value1'$object->some;// 'value2'
Problem description
But what about another case, when you have a plain array with multiple fields and you want to fold them into different objects?
For example, we have the following data to denormalize:
$plainData = ['foo' =>'value1','bar' =>'value2','baz' =>'value3','bam' =>'value4','zam' =>'value5','tam' =>'value6', ...// and so on...]
We can map all of these values to properties in one class, but I want to separate them by some meaning in different objects.
For example, I have the following domain classes:
class Bar{publicfunction__construct(publicstring$valueFive,publicstring$valueThree, ) { }}class Baz{publicfunction__construct(publicstring$valueOne,publicstring$valueSix,publicstring$valueTwo, ) { }}class Request{publicfunction__construct(publicstring$valueFour,// keep fourth value in this class => can be done via #[SerializedName('bam')]publicBar$bar,// fold the properties 5 and 3 in the Bar::class => ?publicBaz$baz// fold properties 1, 6, and 2 in the Baz::class => ? ) { }}
Example
Possible solution
We can allowwildcard for#[SerializedPath]
. For example,#[SerializedPath('[*]')]
or#[SerializedPath('[]')]
which can tell the serializer to look at properties in the current (root) scope.
Example:
$plainData = ['foo' =>'value1','bar' =>'value2','baz' =>'value3','bam' =>'value4','zam' =>'value5','tam' =>'value6', ...// and so on...]class Bar{ publicfunction__construct( #[SerializedName('zam')] public string$valueFive, #[SerializedName('baz')] public string$valueThree, ) { }}class Baz{ publicfunction__construct( #[SerializedName('foo')] public string$valueOne, #[SerializedName('tam')] public string$valueSix, #[SerializedName('bar')] public string$valueTwo, ) { }}class Request{ publicfunction__construct( #[SerializedName('bam')] public string$valueFour, #[SerializedPath('[*]')] public Bar$bar, #[SerializedPath('[*]')] public Baz$baz ) { }}