-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Closed
Labels
2.18Issues planned at 2.18 or laterIssues planned at 2.18 or laterhas-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issueIndicates that there exists a test case (under `failing/`) to reproduce the issue
Milestone
Description
Search before asking
- I searched in the issues and found nothing similar.
Describe the bug
Starting with version 2.18, we get the following exception when deserializing our auto-value-based objects.
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Deserialization (of [simple type, class com.github.bernd.javatests.jackson.JacksonBuilderCreatorSubtype$Animal]) with Builder, External type id, @JsonCreator not yet implemented
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 3, column: 6] (through reference chain: com.github.bernd.javatests.jackson.JacksonBuilderCreatorSubtype$Animals["animals"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1888)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserializeUsingPropertyBasedWithExternalTypeId(BuilderBasedDeserializer.java:828)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserializeWithExternalTypeId(BuilderBasedDeserializer.java:764)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserializeFromObject(BuilderBasedDeserializer.java:318)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserialize(BuilderBasedDeserializer.java:220)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:361)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:246)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:30)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:310)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4917)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3860)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3828)
at com.github.bernd.javatests.jackson.JacksonBuilderCreatorSubtype.main(JacksonBuilderCreatorSubtype.java:101)
Version Information
2.18.0
Reproduction
This example triggers the bug. Our code uses Google's auto-value, but I wrote the example without auto-value to make it easier to debug. The code works with 2.17 but fails with 2.18.
package com.github.bernd.javatests.jackson;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.json.JsonMapper;
import java.util.List;
public class JacksonBuilderCreatorSubtype {
public static class Animals {
@JsonProperty("animals")
public List<Animal> animals;
}
@JsonDeserialize(builder = Animal.Builder.class)
public static class Animal {
@JsonProperty("kind")
public String kind;
@JsonProperty("properties")
public AnimalProperties properties;
@Override
public String toString() {
return "Animal{kind='" + kind + '\'' + ", properties=" + properties + '}';
}
public static abstract class Builder {
@JsonProperty("kind")
public abstract Builder kind(String kind);
@JsonProperty("properties")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "kind")
@JsonSubTypes({
@JsonSubTypes.Type(name = "bird", value = BirdProperties.class),
@JsonSubTypes.Type(name = "mammal", value = MammalProperties.class)
})
public abstract Builder properties(AnimalProperties properties);
@JsonCreator
public static BuilderImpl create() {
return new BuilderImpl();
}
public abstract Animal build();
}
public static class BuilderImpl extends Builder {
private String kind;
private AnimalProperties properties;
public BuilderImpl kind(String kind) {
this.kind = kind;
return this;
}
public BuilderImpl properties(AnimalProperties properties) {
this.properties = properties;
return this;
}
@Override
public Animal build() {
final var animal = new Animal();
animal.kind = kind;
animal.properties = properties;
return animal;
}
}
}
public interface AnimalProperties {
}
public static class MammalProperties implements AnimalProperties {
@JsonProperty("num_teeth")
public int teeth;
@Override
public String toString() {
return "MammalProperties{teeth=" + teeth + '}';
}
}
public static class BirdProperties implements AnimalProperties {
@JsonProperty("color")
public String color;
@Override
public String toString() {
return "BirdProperties{color='" + color + '\'' + '}';
}
}
public static void main(String[] args) throws Exception {
final var jsonMapper = JsonMapper.builder().build();
final var animals = jsonMapper.readValue("""
{
"animals": [
{"kind": "bird", "properties": {"color": "yellow"}},
{"kind": "mammal", "properties": {"num_teeth": 2}}
]
}
""", Animals.class);
animals.animals.forEach(System.out::println);
}
}
Expected behavior
No response
Additional context
No response
Metadata
Metadata
Assignees
Labels
2.18Issues planned at 2.18 or laterIssues planned at 2.18 or laterhas-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issueIndicates that there exists a test case (under `failing/`) to reproduce the issue