32
32
use Symfony \Component \Serializer \Mapping \ClassMetadataInterface ;
33
33
use Symfony \Component \Serializer \Mapping \Factory \ClassMetadataFactoryInterface ;
34
34
use Symfony \Component \Serializer \NameConverter \NameConverterInterface ;
35
- use Symfony \Component \TypeInfo \Exception \LogicException as TypeInfoLogicException ;
36
35
use Symfony \Component \TypeInfo \Type ;
36
+ use Symfony \Component \TypeInfo \Type \BuiltinType ;
37
37
use Symfony \Component \TypeInfo \Type \CollectionType ;
38
38
use Symfony \Component \TypeInfo \Type \IntersectionType ;
39
+ use Symfony \Component \TypeInfo \Type \NullableType ;
39
40
use Symfony \Component \TypeInfo \Type \ObjectType ;
40
41
use Symfony \Component \TypeInfo \Type \UnionType ;
42
+ use Symfony \Component \TypeInfo \Type \WrappingTypeInterface ;
41
43
use Symfony \Component \TypeInfo \TypeIdentifier ;
42
44
43
45
/**
@@ -644,11 +646,9 @@ private function validateAndDenormalizeLegacy(array $types, string $currentClass
644
646
private function validateAndDenormalize (Type $ type , string $ currentClass , string $ attribute , mixed $ data , ?string $ format , array $ context ): mixed
645
647
{
646
648
$ expectedTypes = [];
647
- $ isUnionType = $ type ->asNonNullable () instanceof UnionType;
648
649
$ e = null ;
649
650
$ extraAttributesException = null ;
650
651
$ missingConstructorArgumentsException = null ;
651
- $ isNullable = false ;
652
652
653
653
$ types = match (true ) {
654
654
$ type instanceof IntersectionType => throw new LogicException ('Unable to handle intersection type. ' ),
@@ -667,11 +667,13 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
667
667
$ collectionValueType = $ t ->getCollectionValueType ();
668
668
}
669
669
670
- $ t = $ t ->getBaseType ();
670
+ while ($ t instanceof WrappingTypeInterface) {
671
+ $ t = $ t ->getWrappedType ();
672
+ }
671
673
672
674
// Fix a collection that contains the only one element
673
675
// This is special to xml format only
674
- if ('xml ' === $ format && $ collectionValueType && !$ collectionValueType ->isA (TypeIdentifier::MIXED ) && (!\is_array ($ data ) || !\is_int (key ($ data )))) {
676
+ if ('xml ' === $ format && $ collectionValueType && !$ collectionValueType ->isIdentifiedBy (TypeIdentifier::MIXED ) && (!\is_array ($ data ) || !\is_int (key ($ data )))) {
675
677
$ data = [$ data ];
676
678
}
677
679
@@ -694,8 +696,6 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
694
696
if (TypeIdentifier::STRING === $ typeIdentifier ) {
695
697
return '' ;
696
698
}
697
-
698
- $ isNullable = $ isNullable ?: $ type ->isNullable ();
699
699
}
700
700
701
701
switch ($ typeIdentifier ) {
@@ -731,26 +731,35 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
731
731
}
732
732
733
733
if ($ collectionValueType ) {
734
- try {
735
- $ collectionValueBaseType = $ collectionValueType ->getBaseType ();
736
- } catch (TypeInfoLogicException ) {
737
- $ collectionValueBaseType = Type::mixed ();
734
+ $ collectionValueBaseType = $ collectionValueType ;
735
+ while ($ collectionValueBaseType instanceof WrappingTypeInterface) {
736
+ $ collectionValueBaseType = $ collectionValueBaseType ->getWrappedType ();
738
737
}
739
738
740
739
if ($ collectionValueBaseType instanceof ObjectType) {
741
740
$ typeIdentifier = TypeIdentifier::OBJECT ;
742
741
$ class = $ collectionValueBaseType ->getClassName ().'[] ' ;
743
742
$ context ['key_type ' ] = $ collectionKeyType ;
744
743
$ context ['value_type ' ] = $ collectionValueType ;
745
- } elseif (TypeIdentifier::ARRAY === $ collectionValueBaseType ->getTypeIdentifier ()) {
744
+ } elseif ($ collectionValueBaseType instanceof BuiltinType && TypeIdentifier::ARRAY === $ collectionValueBaseType ->getTypeIdentifier ()) {
746
745
// get inner type for any nested array
747
746
$ innerType = $ collectionValueType ;
747
+ if ($ innerType instanceof NullableType) {
748
+ $ innerType = $ innerType ->getWrappedType ();
749
+ }
748
750
749
751
// note that it will break for any other builtinType
750
752
$ dimensions = '[] ' ;
751
753
while ($ innerType instanceof CollectionType) {
752
754
$ dimensions .= '[] ' ;
753
755
$ innerType = $ innerType ->getCollectionValueType ();
756
+ if ($ innerType instanceof NullableType) {
757
+ $ innerType = $ innerType ->getWrappedType ();
758
+ }
759
+ }
760
+
761
+ while ($ innerType instanceof WrappingTypeInterface) {
762
+ $ innerType = $ innerType ->getWrappedType ();
754
763
}
755
764
756
765
if ($ innerType instanceof ObjectType) {
@@ -832,17 +841,17 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
832
841
return $ data ;
833
842
}
834
843
} catch (NotNormalizableValueException |InvalidArgumentException $ e ) {
835
- if (!$ isUnionType && ! $ isNullable ) {
844
+ if (!$ type instanceof UnionType ) {
836
845
throw $ e ;
837
846
}
838
847
} catch (ExtraAttributesException $ e ) {
839
- if (!$ isUnionType && ! $ isNullable ) {
848
+ if (!$ type instanceof UnionType ) {
840
849
throw $ e ;
841
850
}
842
851
843
852
$ extraAttributesException ??= $ e ;
844
853
} catch (MissingConstructorArgumentsException $ e ) {
845
- if (!$ isUnionType && ! $ isNullable ) {
854
+ if (!$ type instanceof UnionType ) {
846
855
throw $ e ;
847
856
}
848
857
@@ -862,7 +871,7 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
862
871
throw $ missingConstructorArgumentsException ;
863
872
}
864
873
865
- if (! $ isUnionType && $ e ) {
874
+ if ($ e && !( $ type instanceof UnionType && ! $ type instanceof NullableType) ) {
866
875
throw $ e ;
867
876
}
868
877
0 commit comments