Unable to initialise property "type"
Describe the bug My class
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes(
JsonSubTypes.Type(value = ClassA::class, name = "A"),
JsonSubTypes.Type(value = ClassB::class, name = "B"),
JsonSubTypes.Type(value = ClassC::class, name = "C") ...
)
abstract class A() {
lateinit var first: <something>
lateinit var second: <somthing>
lateinit var id: String
lateinit var type: String
lateinit var start: Time ...
}
and data class
data classA(val name: String?, val gender: String) : A() { } ...
data classB() : A() { } ...
To Reproduce
When I deserialise the json to data class, the propert type is not initialised and throws run time exception lateinit property type has not been initialized
However I am able to initialize every other property in class A() like id, first, second and many more
Versions Kotlin: 1.6.21 Jackson-module-kotlin: 2.13.3 Jackson-databind: 2.13.3
Additional context Am I missing any annotation?
Not sure if it'd help but there is separate value As.EXISTING_PROPERTY meant to be used when Type Id is not "virtual" property (that is, matches an actual non-metadata Object property).
Otherwise assumption is that Type Id is just metadata used for type handling and does not map to/from actual Java/Kotlin side property.
Thanks for looking into. I get same error with As.EXISTING_PROPERTY and As.EXTERNAL_PROPERTY
Right, you would not want to use EXTERNAL_PROPERTY, that has different semantics (it expects property within "parent" (enclosing) JSON Object).
But unfortunate that EXISTING_PROPERTY makes no difference.
Ok, whats the solution here?
I don't know, was just trying to suggest things to try. I do not know Kotlin module (or Kotlin) well enough so I hope someone else can comment on specific issue encountered and perhaps offer a work-around.
Found the solution here: https://fasterxml.github.io/jackson-annotations/javadoc/2.4/com/fasterxml/jackson/annotation/JsonTypeInfo.html
Adding visible = true, the property will be passed as-is to deserializers.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
This is not a kotlin-module problem in the least, as I can reproduce it with the following Java code.
Therefore, this issue is closed.
If you have any further discussion on this issue, please submit the issue to databind.
(BTW, the workaround that was shared worked with this code as well)
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class GitHub569 {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes(@JsonSubTypes.Type(value = ClassA.class, name = "A"))
static class A {
private String id;
private String type;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
// Because of another problem, getter is not provided.
public String _getType() { return type; }
public void setType(String type) { this.type = type; }
}
static class ClassA extends A {
}
public static void main(String[] args) throws JsonProcessingException {
ClassA a = new ClassA();
a.setId("id");
ObjectMapper mapper = new ObjectMapper();
String serialized = mapper.writeValueAsString(a);
System.out.println(serialized);
ClassA deserialized = mapper.readValue(serialized, ClassA.class);
System.out.println(deserialized._getType());
}
}
Yes, this is due to Type Erasure: it is STRONGLY RECOMMENDED that polymorphic values are not serialized/deserialized as root-level values but only as nested properties. There are workarounds for the problem but fundamentally Java (and Kotlin to a degree) makes it impossible to avoid the problem: during serialization detected Base Type is different than when deserializing, causing mismatch between expected Type Id on read vs write.