在建立 Quarkus 應用時,RESTful 服務是常見的場景。那就會遇到 kotlin serializer 的選擇。如果是有用到 Kotlin Value Class , Kotlinx serialization 會是比較沒有問題。但是跟 Quarkus 配合會遇到 live Reload 的問題。會噴下面的錯誤,所以我們還是用回來 Jacksonjava.lang.RuntimeException: Unable to invoke Kotlin compiler. java.lang.NoClassDefFoundError: org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoidKt
其實在 Jackson serialization 處理 value class 。大部份情況也沒有問題。objectMapper 也會自動加上 kotlin Moudle. 目前遇到以下兩種需要 workaround
如以下的 List 包住演員 (Actor), 如果不作處理會出 Exception InvalidDefinition Cannot construct instance of (no Creators, like default constructor, exist): no String-argument constructor/factory
@JvmInline
value class Actor(val raw: String)
data class FilmWithActor(
val episodeId: EpisodeId,
val title: Title,
val director: Director,
val actors: List<Actor>
)
加上一個客製的 Creator 就會成功 decode
@JsonDeserialize(using = ActorDeserializer::class)
@JvmInline
value class Actor(val raw: String)
class ActorDeserializer : JsonDeserializer<Actor>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Actor {
val str: String = p.readValueAs(String::class.java)
return Actor(str)
}
}
以下這種情況會無法 decode, 但是其實如果只有一個field, 表示那也不需要 Data Class 這層 wrapper, 應該 value class 本身就可以代表 Domain model,在設計上不該出現這種。
value class MyInlineClass(val i: Int)
data class MyDataClass(val i: MyInlineClass)
如果真的需要的話。可以加上一個假欄位再用 @JsonIgnore 無視
data class MyDataClass(val i: MyInlineClass, @JsonIgnore val _i:Int=0)