-
-
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
Deserialization of a polymorphic type based on presence of a property #1627
Comments
I could have sworn there was already an issue filed years ago, but I guess not. As far as desirability of such a feature, I think that yes, it would be nice to have. It has been requested a few times, and I can see benefits. There are two main questions regarding implementing this:
I guess there are 2 major approaches (minimal / maximal). Minimal approach would simply allow listing of properties, existence of which would infer matching subtype to use. Implementation just might be possible without major changes to type id resolver, for deserialization. For serialization it might be even easier as it would be similar to basic Maximal (or, "non-minimal"?) approach, on the other hand, would require more changes. Does above make sense? Timeline-wise, this would be 3.x (perhaps even 3.0) feature I think? |
If anyone cares, I've written a simple custom deserializer that handles this case here: https://stackoverflow.com/a/50013090/1030527 |
I've written a solution quite some time ago (not long after this issue was created) that proved to work well. It leverages existing annotation JsonSubTypes to select the class to deserialize to for name of present property.
@cowtowncoder do you think this is good enough for PR? |
@lpandzic I appreciate the offer but I don't think this fits with the design since it couples content deserialization with type handling (which usually would be handled by |
Yes I agree, but the functionality should be added in some form to the jackson itself, something like |
@cowtowncoder Can you provide some rough guidelines on how to create and use such a custom
I'm not familiar with all of Jackson's internals and I can't find any useful examples of a custom I understand that many (most?) use-cases do not need the intermediate representation as a Also, to give a bit of context, my use-case is a JSON tree of objects where nodes can be branches or leaves so I need to handle embedded (list of) objects. |
@lpandzic Yes, I am not at all opposed to the idea itself, or for annotation style (although annotation information will limit what may be passed, to some degree). So it is more a question of how to model things to work so that deserializer part only needs to handle actual data, but leave handling of type- and identity-metadata to other handlers. This matters a lot due to wide number of (de)serializers, multiplied by alternative type/id handlers available. @berniegp One way forward would be to start with annotation + use case, showing how test with annotations should pass. To give an idea of how it would be used. My expectation would be that users should not have to implement any of core types. |
@cowtowncoder, I'd propose a model for implementation but current model (JsonTypeInfo and related annotations) isn't 100% clear to me. Does it make sense to expand those annotations and add support for this use case on them? |
Any update on this? |
Upvoted. This would be extremely useful when you:
|
At this point there is not much use for upvoting: I do not have time to work on this, so it will have to be someone with both time and itch to get it done. @lpandzic I wish I could suggest specific approach. I think that extending |
Am I right in understanding that In short, it doesn't seem possible to build a performant custom deserializer based on the presence of a property. Is this correct? |
FYI if anyone is interested, here's the source of the working prototype I mentioned on stackoverflow. |
@lpandzic Thank you for sharing ths! @berniegp Yes, I think your summary is correct. The only addition I would make is that although performance is one aspect to it, bigger problem is that existing mechanisms, extension points assume streaming reads, no buffering. So I am not against supporting something that does require buffering (this is already required by polymorphic deserialization if Type Id happens to be "somewhere in the middle"), but it does require bigger changes outside immediate handlers. |
Thanks @lpandzic. Does this implementation support @JsonUnwrapped? For example: class UnwrappedPojo { {"name": "This is a foo", "foo": "foo"} |
I've rarely, if ever, used @JsonUnwrapped and haven't tested it. With that said, I don't see why it shouldn't work. |
FYI I've published Infobip Jackson Extension module which provides a way to tackle this issue: interface FooBar extends PresentPropertyJsonHierarchy<FooBarType> {
}
@AllArgsConstructor(onConstructor_ = @JsonCreator)
@Value
static class Foo implements FooBar {
private final String foo;
}
@AllArgsConstructor(onConstructor_ = @JsonCreator)
@Value
static class Bar implements FooBar {
private final String bar;
}
@Getter
@AllArgsConstructor
enum FooBarType implements TypeProvider {
FOO(Foo.class),
BAR(Bar.class);
private final Class<? extends FooBar> type;
} |
Now that #43 is implemented for 2.12 -- introducing |
@cowtowncoder Very cool! Thanks for the update! |
I'd like a feature on jackson for deserialization of polymorphic type where type selection strategy should be based on presence of a property. I know this was mentioned before but there was no consensus about how it should be solved.
Example:
For jsons like:
{'foo':''}
{'bar':''}
and type definitions like:
When I deserialise FooBar with
{'foo':''}
I should get an instance of a Foo and similar for{'bar':''}
I should get an instance of a Bar.I have a working prototype where you have to specify a new custom deserialiser like:
and this is a valid approach, but a better one, in my opinion, would be if this had first class support for example with JsonTypeInfo:
Thoughts?
The text was updated successfully, but these errors were encountered: