-
-
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
Discriminator is not written polymorphic object is assigned to generic property #4422
Comments
Couple of things:
|
Can you just run the code, please :D |
This is the same thing without context, just the crash: @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "valueType")
@JsonSubTypes({
@JsonSubTypes.Type(value = PolyParent.PolyChild.class, name = "CHILD")
})
public sealed interface PolyParent {
record PolyChild() implements PolyParent { }
record Generic<T>(T c) { }
static void main(String[] args) throws JsonProcessingException {
ObjectMapper jackson = new ObjectMapper();
String gs = jackson.writeValueAsString(new Generic<PolyChild>(new PolyChild()));
jackson.readValue(gs, new TypeReference<Generic<PolyChild>>() {
});
}
} To be clear: There is no assertion here, because the code simply crashes. |
Ah. I did indeed miss inline And you are right, it is indeed round-trip test :) Looking into this now (without running code yet), this is almost certainly due to good old Java Type Erasure. You cannot use generic types as root values without work-arounds since there is no runtime type information about
So for (3) you would do something like:
and that would then include type id. Without doing so, all Jackson sees is an instace of Hope this helps (this is a VFAQ). |
Oh man, I could swear had actually tried (3) - which I wouldn't even consider a workaround. But yeah, it works just fine with the toy example. Thanks for your quick response! |
@Tillerino ah no problem & apologies for mis-reading your issue here. I hope it works out. |
Hi there, just to confirm the workaround: Writing with a I am a little confused about the reason, though. You're saying that type erasure is the issue here. But it looks weirder. I would expect type erasure to lead to the object being serialized as In my example above, this doesn't come across - I tried to keep it minimal after all. So consider the following, modified example, where I added a field to the @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "valueType")
@JsonSubTypes({
@JsonSubTypes.Type(value = PolyParent.PolyChild.class, name = "CHILD")
})
public sealed interface PolyParent {
record PolyChild(String polyChildField) implements PolyParent { }
record Generic<T>(T genericField) { }
static void main(String[] args) throws JsonProcessingException {
ObjectMapper jackson = new ObjectMapper();
String gs = jackson.writeValueAsString(new Generic<>(new PolyChild("S")));
System.out.println(gs);
jackson.readValue(gs, new TypeReference<Generic<PolyParent>>() {
});
}
} (The same crash as before, obviously, nevermind that). The output is {"genericField":{"polyChildField":"S"}} so clearly the fields of {"genericField":{}} because I expect |
Search before asking
Describe the bug
Sorry, I struggled to find a good title. So basically, Jackson always writes and requires the discriminator of a polymorphic type P, even if the extending type C of P is known. However, if an instance of C is assigned to a generic property, then the discriminator is not written. This is impossible to describe, just look at the example 😆
Version Information
2.16.1
Reproduction
So there is a polymorphic type
PolyParent
with one child typePolyChild
, the type info is set up in a pretty standard fashion.If
PolyChild
is a property of a regular object (where the property has the concrete typePolyChild
), serialization works as expected - a round trip works just fine.If an instance of
PolyChild
is assigned to a generic property, then the serialization will not include the descriminator and deserialization will fail.Expected behavior
The serialization-deserialization-roundtrip works in both cases.
Additional context
You can see that the output of
System.out.println(gs);
doesn't contain the discriminator, I guess that's the issue.The text was updated successfully, but these errors were encountered: