fix(transformer): cast inner values of array properties when mapping from untyped sources#330
fix(transformer): cast inner values of array properties when mapping from untyped sources#330nlemoine wants to merge 1 commit intojolicode:mainfrom
Conversation
…from untyped sources When mapping from array/stdClass sources to DTOs with PHPDoc-typed array properties (e.g. `@var array<int>`), inner values were not cast because FromTargetMappingExtractor mirrors the target type to source, making both identical. BuiltinTransformer(int, int) then passes values through. Override source collection value type to mixed in ArrayTransformerFactory when the source is untyped and value types are identical mirrored scalars. This triggers MixedTransformerFactory → BuiltinTransformer(mixed, target) which generates proper casts. Also add missing bool entry in BuiltinTransformer CAST_MAPPING for mixed.
|
Hey @nlemoine, What do you think about this way of doing it ? |
|
Hello @Korbeil, Sure, preserving current behavior is totally legit. I'll update this soon. Note that I also have an upcoming PR to handle array shapes. I was just waiting for this one feedback. One thing, I would push ee1272a#diff-c48da6ba30bec3efb1de38fc5cf4f40129a4b3d5d1c329f0b6bde2e148855ae9R39 into the current main since it's a "bug" from actual implementation. I can submit a separate PR if needed. |
Don't think it need a feature flag for that, we have enough of them, use case / tests seems correct for me 👍 for merging this |
Hi @joelwurtz,
I finally got the chance to test the feature addressing my original issue. Works great using attributes, thanks again!. However, I just wondered if that could be done using phpdoc only. Because having to leverage attributes feels a bit redundant for those use cases:
FromTargetMappingExtractor::transformTargetType()mirrors target types to source for untyped sources (array, stdClass, LazyMap). Forarray<int>, the source value type becomesint- identical to target.BuiltinTransformer(int, int)sees matching types and returns input unchanged, skipping the cast.Solution
In
ArrayTransformerFactory, detect when source is untyped and the collection value types are identical mirrored scalars, then override the source value type tomixed. This makes the chain resolve toBuiltinTransformer(mixed, target_type)which generates explicit casts.Nullable types (
array<int|null>) are handled via manualNullableTransformerwrapping sinceNullableType(mixed)is impossible in Symfony TypeInfo.Also adds the missing
boolentry inBuiltinTransformer::CAST_MAPPING[mixed].Let me know if this needs change.