Enumもカスタムタイプのパースと同じく、 Serializer
を作成しなければなりません。Jacksonは @JsonCreator
と @JsonValue
だけでできるので、少し面倒に感じましたが、メリットはあります。
Stringの値でパースする abstract
なシリアライザを作成しました。
internal interface StringEnum { public val label: String? companion object { internal abstract class Serializer<T : Enum<T>>(private val kClass: KClass<T>) : KSerializer<T?> { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(this::class.jvmName, PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: T?) { when (val label = (value as StringEnum).label) { null -> encoder.encodeNull() else -> encoder.encodeString(label) } } override fun deserialize(decoder: Decoder): T? { val value = decoder.decodeString() return kClass.java.enumConstants .firstOrNull { (it as StringEnum).label == value } } } } }
このように定義します。
@Serializable(Type.Companion.Serializer::class) enum class Type() : StringEnum { ONE { override val label: String = "one" }, TWO { override val label: String = "two" }, ; companion object { object Serializer : StringEnum.Companion.Serializer<Type>(Type::class) } }
このように使用します。
@Serializable internal data class Root( @SerialName("type") val type: Type? )
nullableにしないとコンパイル時にエラーが出るのでそこは安全です。サーバーで新しい値が定義された時はパースの失敗ではなく、nullになるので安全です。
バージョン情報
plugins { kotlin("jvm") version "1.4.30" kotlin("plugin.serialization") version "1.4.10" } dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1") }