FasterXML / FasterXML/jackson-module-kotlin

Kotlin default values do not work for missing fields when using polymorphism with JsonTypeInfo.As.EXTERNAL_PROPERTY

Open
#249 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
Kotlin
Stars
1.2k
Forks
187
Avg merge
9h 48m
Merged PRs (30d)
16

Description

```kotlin
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.annotation.NoClass
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue

sealed class Entity
data class Bacteria(val speciesName: String): Entity()
data class Disease(val diseaseId: Long): Entity()

enum class EntityType {
MY_Bacteria,
MY_Disease
}

data class MyRequestBody(
val entityType: EntityType,
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "entityType",
defaultImpl = NoClass::class,
visible = true
)
@JsonSubTypes(
JsonSubTypes.Type(value = Disease::class, name = "MY_Disease"),
JsonSubTypes.Type(value = Bacteria::class, name = "MY_Bacteria")
)
val entity: Entity? = null
)

fun main() {
val jsonString = """{
| "entityType": "MY_Bacteria"
|}""".trimMargin()
val reader = jacksonObjectMapper()
val deserialized = reader.readValue(jsonString)
println(deserialized)
}
```

results in
```
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Missing property 'entity' for external type id 'entityType'
at [Source: (String)"{
"entityType": "MY_Bacteria"
}"; line: 3, column: 1]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1356)
at com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler.complete(ExternalTypeHandler.java:281)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeUsingPropertyBasedWithExternalTypeId(BeanDeserializer.java:1001)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:853)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:324)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3023)
at MainKt.main(Main.kt:40)
at MainKt.main(Main.kt)
```

However, if we change it to use `JsonTypeInfo.As.PROPERTY`, it works for the missing field
```kotlin
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.annotation.NoClass
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue

sealed class Entity(val entityType: EntityType)
data class Bacteria(val speciesName: String): Entity(EntityType.MY_Bacteria)
data class Disease(val diseaseId: Long): Entity(EntityType.MY_Disease)

enum class EntityType {
MY_Bacteria,
MY_Disease
}

data class MyRequestBody(
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "entityType",
defaultImpl = NoClass::class,
visible = true
)
@JsonSubTypes(
JsonSubTypes.Type(value = Disease::class, name = "MY_Disease"),
JsonSubTypes.Type(value = Bacteria::class, name = "MY_Bacteria")
)
val entity: Entity? = null
)

fun main() {
val jsonString = "{}"
val reader = jacksonObjectMapper()
val deserialized = reader.readValue(jsonString)
println(deserialized)
}
```
It successfully prints `MyRequestBody(entity=null)`

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.