Skip to content

Collection deserializer should create empty collection instead of null (when input is null) #722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pjfanning opened this issue Mar 29, 2025 · 7 comments
Labels

Comments

@pjfanning
Copy link
Member

pjfanning commented Mar 29, 2025

@pjfanning pjfanning added the 2.19 label Mar 29, 2025
@pjfanning pjfanning changed the title collection deserializer should create empty collection instead of null Collection deserializer should create empty collection instead of null (when input is null) Mar 29, 2025
@psliwa
Copy link

psliwa commented May 13, 2025

In my opinion this change is unsafe. With this change when DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES is used and collection value is null then exception is not thrown (https://github.com/FasterXML/jackson-module-scala?tab=readme-ov-file#deserializationfeaturefail_on_null_creator_properties - this documentation is outdated). I would expect exception in such case would be thrown. It is impossible right now to configure jackson to old behaviour - to throw exception when collection value in json is missing or is null. It can be useful in few use cases - eg in my use case I would like to detect null values for collection for unexpected schema changes - it is better to detect such schema changes during deserialization (in api or database) and throw exception rather that use empty collection (which may cause invalid data passed to application logic).

Could this PR be re-considered and above concerns could be taken into account? In my opinion without any feature flag this change is a bug. For java collection behaviour is assigning null values for null json properties and FAIL_ON_NULL_CREATOR_PROPERTIES feature flag works.

@pjfanning
Copy link
Member Author

I have no current plans to revert this. The change is more consistent with the Java collection deserialization.
Jackson is very configurable. It is very pluggable. It is one option to subclass the deserializer in this module and to modify the behaviour in the subclass.

@pjfanning
Copy link
Member Author

pjfanning commented May 13, 2025

@psliwa if you are interested in submitting a PR, I will review it - but the PR needs proof that the behaviour in this module for a Scala List differs from how jackson-databind deals with a Java List. And also, Scala developers tend to hate nulls.

Have you considered having an Option[List[T]] in your class so that you can check for null input (which should deserialize as None) and empty input (which should deserialize as Some(List.empty))

@pjfanning
Copy link
Member Author

I've update the README.

@psliwa
Copy link

psliwa commented May 13, 2025

Thanks for your comments. It is easy to check how Java collections handing differs from Scala collections after this merge, I can provide later some snippet to show difference but preparing PR knowing it will be rejected doesn't make sense to me. Java collections handling honor FAIL_ON_NULL_CREATOR_PROPERTIES property, null is deserialized to null. Deserializing null to empty collection by default and without any configuration possibilities in my opinion is strange behaviour even in scala ecosystem. Adding Option[List[???]] also doesn't make sense in such cases because such field is not optional from application level - the best way would be to use FAIL_ON_NULL_CREATOR_PROPERTIES in order to force null check in convenient way. I am not sure how it works in Scala 3 (you mentioned this in PR description) so maybe I don't have full context and this is why for me this behaviour is strange and unsafe.

@pjfanning
Copy link
Member Author

pjfanning commented May 13, 2025

@psliwa I merged #733 and there is a 2.19.1-SNAPSHOT with this change

@psliwa
Copy link

psliwa commented May 13, 2025

Many thanks 🙏 Solution in this new PR looks like good compromise, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants