-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Add a Deserialisation Feature to read null and missing fields as empty collections. #1258
Conversation
@@ -354,7 +354,11 @@ protected JsonToken _initForReading(JsonParser p) throws IOException | |||
t = p.nextToken(); | |||
if (t == null) { | |||
// Throw mapping exception, since it's failure to map, not an actual parsing problem | |||
throw JsonMappingException.from(p, "No content to map due to end-of-input"); | |||
if (this._config.hasDeserializationFeatures(DeserializationFeature.READ_NULL_AS_EMPTY_COLLECTION.getMask())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this one: note that this does not mean JSON null
token, but actual physical end-of-input.
So I don't think it should fall under this feature; another feature could of course allow consider end-of-input as null equivalent, and thereby return either null
or empty collection or whatever other coercions might be applicable.
Ok first of all, thank you for the contribution. I know many users have requested this feature. Due to size of changes I will need to spend more time looking through, but here are some initial thoughts (in addition to couple of notes I already added):
One thing that I wonder, now, is that perhaps what would make most sense would be to instead add a new hook that would allow external definition of "empty" and "null" values. If so, handling could be externalized; and even if a simple/default implementation would be provided for convenience, users and/or library (scala module) authors could develop more advanced and use-case specific solutions. Would such an approach make sense? I am not 100% sure how handler should be defined, but should probably be called from |
re scope and name: re BeanDeserializer: re Dynamic DeserializationFeatures re A customizable hook Intriguing! That would certainly allow the most flexibility. Happy to jump on IRC sometime if you want someone to rubber duck as you design. :) |
@HolyHaddock valid point about possibility of too many features. I would be fine with renaming of proposed feature to something where "Collection" would be replaced by something like "Container"; I think that is the term used within Jackson codebase to refer to structured types (although whether it covers referential types -- that is, Option(al) -- is bit ambiguous). As to iteration: what I would do differently could be quite simple (although I haven't checked feasibility yet); instead of letting caller (BeanDeserializer) worry about null to empty conversion, let container deserializer handle that: you are already passing the boolean flag so it knows whether such coercion is warranted. If so, it should be able to handle it transparently. This would also work better with delegation by other types. On dynamic features: it is perfectly fine to change state of any or all
and this means that state of a particular feature at point of deserializer construction may not be state at actual use. As such, general contract is that state should be determined at point of use. But patch as is defines things so that state of new feature is checked when constructing |
The feature name and docs have been improved as discussed. re: iteration It would be nice not to build up the Set of property names if the feature was disabled - I'll have a think about how to do that later. |
Ok yes, if missing fields also need to be substituted, yes (although efficiently using bitfield/bitmask like with required property handling) but I do not anticipate that feature to be added at this point. Only mapping from explicit I guess I wasn't clear on my distaste of value defaulting: I am not fully sure it even belongs to databinding layer at all. POJOs may set default values, and should do so where necessary. Translation of But. If and when |
@@ -355,7 +355,11 @@ protected JsonToken _initForReading(DeserializationContext ctxt, JsonParser p) | |||
t = p.nextToken(); | |||
if (t == null) { | |||
// Throw mapping exception, since it's failure to map, not an actual parsing problem | |||
ctxt.reportMissingContent(null); // default msg is fine | |||
if (this._config.hasDeserializationFeatures(DeserializationFeature.READ_NULL_OR_MISSING_CONTAINER_AS_EMPTY.getMask())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is semantically different, as it is actually missing the whole JSON content (which makes it invalid; empty content is not a valid JSON value), so I don't think it is right to map it to anything. If such handling of invalid content is desired it should be fully separate feature, especially as it would apply to all content. I am not necessarily against such a feature but it belongs to a different issue/patch.
At this point I think that implementation of #1402 will implement "null to empty Collection/array/Map" part; and remaining problem of missing values will need to be handled separately. Since there are conflicts and some of code is likely not needed or is incompatible, I will close this PR. I am open to possibility of further work wrt missing values of course, so this is not due to patch being refused or such. It actually helped with implementation of #1402. |
Super. We ended up resolving this problem through the use of a different library, so I have no more itch to scratch here. Thank you for the prompt and fulsome feedback! |
Here's a basic approach - feels a bit blunt-force, but it seems to get the job done.
I'm afraid I don't understand contextual deserializers at all. There seems to be a problem where removing the check for the feature in BeanDeserializer#290 breaks a number of the contextual tests. The check gets them passing again, but it would be good to validate it with someone who better understood what was going on with that.
Should I add some user documentation? If so, where?
As discussed here: FasterXML/jackson-module-scala#257