-
-
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
Polymorphic subtype deduction from available fields #2813
Conversation
Wow. Thank you for contributing this! I will need to read through this with thought and see what I think wrt implementation -- the idea itself has been around for a while and is highly requested. I think #43 is the matching issue? |
|
||
BitSet fingerprint = new BitSet(nextField.get() + properties.size()); | ||
for (BeanPropertyDefinition property : properties) { | ||
fingerprint.set(fieldBitIndex.computeIfAbsent( |
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.
Unfortunately I think this is Java 8 feature, Jackson 2.x (at least until 2.12) can not make use of it.
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.
I actually wrote this POC as a standalone deserializer against 2.11 first so have the non J8 version already to hand (hardly rocket science). Are you saying that master (3.x) must still use Java 7 JDK ops so they can be backported (2.x)?
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.
No, master (3.x) can use Java 8 features just fine. 2.x not. Actually I did not notice this was against master
, so in that sense it would actually work.
But I think I would really like to get this in for 2.12 :)
Interestingly simple, I like this as a starting point! I think I would like to extend support via dedicated annotation changes: this would require support on serialization side too (probably nothing too complex as it should be something like Question of duplicates is interesting, what to do; my initial instinct is to force an exception in such cases to avoid both odd failure cases ("why did it deserialize as X and not Y") and especially "accidentally working first, the not" (if choice of which subtype to use was not stable). But if no exception thrown, specific rule should be clear (like alphabetic ordering of full class name, take first). |
Fail-fast is the goal here. If detected at initialisation then I simply didn't know what Exception class to throw so left it commented out. Please advise. Proposed solution works only for mutually-exclusive subtypes where one and only one must match. There is no ordering requirement and it's simple to infer what's happening inside the box. (!) I'll see what I can do to generalise this towards becoming |
Agreed, simple mutually-exclusive version first makes sense. I think that we will actually get flattened hierarchy already (that is, I would really like to see this for 2.12, given that it has been requested quite often by users. As to exception type, if none of existing exceptions under |
This operates the same as EXISTING_PROPERTY (by looking ahead in the parser to determine the type) so should reuse the classes as much as possible.
Depends upon annotation update here: FasterXML/jackson-annotations#175 |
Apologies for the delay: I finally managed to merge Java14 Record support and will focus on this big ticket item next! |
Merged in both for 2.12 and master, will be in 2.12.0! |
Psst, you put my name in the release notes as Mark not Marc :) |
@drekbour Sorry about that. Fixed. |
AsDeductionTypeDeserializer
implements inferential deduction of a subtype from the fields. As a POC not intended for merging, tere's an amount of cut'n'paste code etc but I thought a functional PR would be the best basis for discussion of something I write out of interest.It works by fingerprinting the full set of possible fields of each subtype on registration. On deserialisation, available fields are compared to those fingerprints until only one candidate remains. It specifically only looks at immediate-child field names as is immediate-child values are covered by existing mechanisms and deeper analysis is a much more imposing ML task not really part of Jackson's remit.
turns into fingerprints (stored as a BitSet)
Which will deserialise the following without it requiring any type markers
When combined with a tool to auto-register subtypes by classpath-scanning, this provides a pure-Java means to extend parent types defined in upstream libraries (imagine a third-party project defines
class Bot extends Identity
)Against number of fields, it is O(1) space and O(N) time (worst case being unique match always on last incoming field). It has all the obvious caveat-emptor about trusting the source of incoming data etc
The ideal goal would be to support this through the core typing annotations as
@JsonTypeInfo(use = DEDUCTION)
. Please provide some feedback and let me know if it's worth my time to rewrite this full integration