18
18
use Symfony \Component \Serializer \Exception \NotNormalizableValueException ;
19
19
use Symfony \Component \PropertyInfo \PropertyTypeExtractorInterface ;
20
20
use Symfony \Component \PropertyInfo \Type ;
21
+ use Symfony \Component \Serializer \Exception \RuntimeException ;
21
22
use Symfony \Component \Serializer \Mapping \AttributeMetadataInterface ;
23
+ use Symfony \Component \Serializer \Mapping \ClassDiscriminatorResolver ;
24
+ use Symfony \Component \Serializer \Mapping \ClassDiscriminatorResolverInterface ;
22
25
use Symfony \Component \Serializer \Mapping \Factory \ClassMetadataFactoryInterface ;
23
26
use Symfony \Component \Serializer \NameConverter \NameConverterInterface ;
24
27
@@ -38,11 +41,17 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
38
41
private $ attributesCache = array ();
39
42
private $ cache = array ();
40
43
41
- public function __construct (ClassMetadataFactoryInterface $ classMetadataFactory = null , NameConverterInterface $ nameConverter = null , PropertyTypeExtractorInterface $ propertyTypeExtractor = null )
44
+ /**
45
+ * @var ClassDiscriminatorResolverInterface
46
+ */
47
+ protected $ classDiscriminatorResolver ;
48
+
49
+ public function __construct (ClassMetadataFactoryInterface $ classMetadataFactory = null , NameConverterInterface $ nameConverter = null , PropertyTypeExtractorInterface $ propertyTypeExtractor = null , ClassDiscriminatorResolverInterface $ classDiscriminatorResolver = null )
42
50
{
43
51
parent ::__construct ($ classMetadataFactory , $ nameConverter );
44
52
45
53
$ this ->propertyTypeExtractor = $ propertyTypeExtractor ;
54
+ $ this ->classDiscriminatorResolver = $ classDiscriminatorResolver ?: new ClassDiscriminatorResolver ();
46
55
}
47
56
48
57
/**
@@ -101,6 +110,27 @@ public function normalize($object, $format = null, array $context = array())
101
110
return $ data ;
102
111
}
103
112
113
+ /**
114
+ * {@inheritdoc}
115
+ */
116
+ protected function instantiateObject (array &$ data , $ class , array &$ context , \ReflectionClass $ reflectionClass , $ allowedAttributes , string $ format = null )
117
+ {
118
+ if ($ mapping = $ this ->classDiscriminatorResolver ->getMappingForClass ($ class )) {
119
+ if (!isset ($ data [$ mapping ->getTypeProperty ()])) {
120
+ throw new RuntimeException (sprintf ('Type property "%s" not found for the abstract object "%s" ' , $ mapping ['typeProperty ' ], $ class ));
121
+ }
122
+
123
+ $ type = $ data [$ mapping ->getTypeProperty ()];
124
+ if (null === ($ class = $ mapping ->getClassForType ($ type ))) {
125
+ throw new RuntimeException (sprintf ('The type "%s" has no mapped class for the abstract object "%s" ' , $ type , $ class ));
126
+ }
127
+
128
+ $ reflectionClass = new \ReflectionClass ($ class );
129
+ }
130
+
131
+ return parent ::instantiateObject ($ data , $ class , $ context , $ reflectionClass , $ allowedAttributes , $ format );
132
+ }
133
+
104
134
/**
105
135
* Gets and caches attributes for the given object, format and context.
106
136
*
@@ -133,7 +163,13 @@ protected function getAttributes($object, $format = null, array $context)
133
163
return $ this ->attributesCache [$ class ];
134
164
}
135
165
136
- return $ this ->attributesCache [$ class ] = $ this ->extractAttributes ($ object , $ format , $ context );
166
+ $ attributes = $ this ->extractAttributes ($ object , $ format , $ context );
167
+
168
+ if ($ mapping = $ this ->classDiscriminatorResolver ->getMappingForMappedObject ($ object )) {
169
+ array_unshift ($ attributes , $ mapping ->getTypeProperty ());
170
+ }
171
+
172
+ return $ this ->attributesCache [$ class ] = $ attributes ;
137
173
}
138
174
139
175
/**
0 commit comments