iT邦幫忙

2022 iThome 鐵人賽

0

在建立 Quarkus 應用時,RESTful 服務是常見的場景。那就會遇到 kotlin serializer 的選擇。如果是有用到 Kotlin Value Class , Kotlinx serialization 會是比較沒有問題。但是跟 Quarkus 配合會遇到 live Reload 的問題。會噴下面的錯誤,所以我們還是用回來 Jackson
java.lang.RuntimeException: Unable to invoke Kotlin compiler. java.lang.NoClassDefFoundError: org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoidKt

https://ithelp.ithome.com.tw/upload/images/20221108/20135701Q7zrHpM1Am.png

其實在 Jackson serialization 處理 value class 。大部份情況也沒有問題。objectMapper 也會自動加上 kotlin Moudle. 目前遇到以下兩種需要 workaround

用 List 包住 Value Classes

如以下的 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)
    }
}

Data Class 只有一個 value field 時會錯

以下這種情況會無法 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)

https://github.com/hmchangm/getting-start-QK/blob/master/src/test/kotlin/tw/brandy/ironman/InlineJacksonTest.kt


上一篇
在 Quarkus 使用 Kotlin Inline Value Class
系列文
Quarkus, Kotlin, Reactive 雲原生服務開發32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言