Ссылка в комментарии pL4Gu33 привела меня в правильном направлении, но потребовались некоторые дополнительные поиски и манипуляции, собирая информацию здесь и там, чтобы найти решение, которое наконец заработало бы, поэтому я подытоживаю его здесь для полноты.
Беда в том, что вам понадобятся две аннотации, одна для интерфейса и одна для реализующих классов, комбинированное использование которых выглядит несколько плохо документированным. Сначала на интерфейсе добавьте эту аннотацию. В отличие от некоторых учебных пособий, дальнейшая аннотация интерфейса не требуется:
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
interface YellowOpsEvent {
val user: String
val partner: String
val subject: String
val change: NatureOfChange
}
Согласно некоторым документам, одного этого должно быть достаточно для десериализации пропплера. Однако контроллер весенней загрузки выдает исключение, поскольку переданное имя root не соответствует ожидаемому классу.
// the above will throw an exception when the serialization product is sent to this controller:
@PostMapping("/event")
fun writeEvent(@RequestBody event: YellowOpsEvent) { // < I expect this not to throw an exception
val bugme = event is StatusChangedEvent // < I expect this to return true if I send the proper event data.
}
Чтобы исправить это, добавьте аннотацию @JsonRootName для любых реализующих классов , с именем интерфейса . Большая часть документации этой аннотации не использует ее для этого, а просто для переименования типа, и даже когда она упоминается в связанном вопросе в контексте полиморфизма, она ошибочно использует свое собственное имя. Вот как это должно выглядеть:
@JsonRootName("YellowOpsEvent")
data class StatusChangedEvent(override val user: String,
override val partner: String,
override val subject: String,
val before: String,
val after: String): YellowOpsEvent {
override val change = NatureOfChange.Changed
}
Теперь это работает! :)