Skip to content

Conversation

jonmldr
Copy link
Contributor

@jonmldr jonmldr commented Jul 30, 2025

This implementation introduces the ability to serialize associative arrays as objects based on the added configuration. It determines whether an array is associative by analyzing doc-comment annotations.

Doc-comments are used since they provide the most consistent type information about array types. Empty arrays cannot be analyzed at runtime to determine whether they represent lists or maps, since they are identical in structure regardless of their intended type.

For promoted properties, type information is extracted from the @param type hint in the constructor doc-comment, for class properties from the @var type hint in the property doc-comment, and for methods from the @return type hint in the method doc-comment.

Pre-assignment array transformation

Arrays are cast immediately before property assignment. This cannot be done in the SerializeArrayItems property serializer because it lacks access to the extracted PropertyType information.

Since identifying associative arrays by analyzing doc-comment type hints requires reflection, which compromises performance, handling this within the SerializeArrayItems property serializer would be suboptimal given that property serializers are called directly by the optimized object mapper.

Recursive processing

The casting of associative arrays does not apply recursively, meaning the format of nested associative arrays remains unchanged. This behavior is reasonable from a serialization standpoint, as associative arrays should be handled as unstructured objects where no guarantees can be provided about their nested elements.

From a hydration perspective, this behavior is compatible with existing functionality. The format of nested associative arrays within parent associative arrays also remains unchanged.

Limitations

Values are cast to objects regardless of applied property serializers. This approach is reasonable given that associative arrays are unlikely to be represented as types other than (associative) arrays or objects, and property serializers are unlikely to deviate from this representation. Furthermore, when serializeMapsAsObjects is explicitly enabled, the consistent object casting aligns with the intended configuration.

Backward compatibility

This implementation introduces a breaking change by adding the typeFromProperty() and typeFromMethod() methods to the PropertyTypeResolver interface. Since this interface is not marked as @internal, adding new methods constitutes a BC break for any existing implementations of this interface.

Associative arrays are not cast to objects by default, so no behavioral breaking changes are introduced and existing serialization behavior is preserved.

Documentation: #serializing-maps-as-objects

@jonmldr jonmldr force-pushed the serialize-associative-arrays-as-objects branch 3 times, most recently from 11ac03e to ffab921 Compare September 19, 2025 12:38
@jonmldr jonmldr force-pushed the serialize-associative-arrays-as-objects branch from ffab921 to 7c7f2c7 Compare September 19, 2025 12:40
@jonmldr
Copy link
Contributor Author

jonmldr commented Sep 19, 2025

Hey @frankdejonge, this PR is ready for review, can you please give it a look? 🙏

@frankdejonge
Copy link
Member

Hi @jonmldr, I'm looking over this PR, and I'm wondering if this could be achieved by using a caster? From what I understand, it's not a global "serialize associative arrays as objects" flag, but more specific and (if I'm honest) it's not quite clear why, and I don't really understand the rationale. When you say Values are cast to objects regardless of applied property serializers, I'm not really understanding what that means.

@jonmldr jonmldr force-pushed the serialize-associative-arrays-as-objects branch 2 times, most recently from c282dd3 to 7c7f2c7 Compare October 7, 2025 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants