はじめに
現時点(2020/3/28)では、kotlinx.serialization
はinline class
をサポートしていません。(ロードマップにはあるみたいですが...)
https://youtrack.jetbrains.com/issue/KT-28791
なので、コンストラクタを2つ使用すると擬似的に使用できます。
環境
Android Studio 4.0 Beta 3
build.gradle.kts(Project)
buildscript {
dependencies {
classpath("org.jetbrains.kotlin:kotlin-serialization:1.3.70")
}
}
build.gradle.kts(app)
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0")
}
他の依存関係はよしなに
コード
Tag.kt
inline class TagId(val value: String = "")
@Serializable
data class Tag private constructor(
@SerialName("tag_id") private val _id: String,
@SerialName("followers_count") val followersCount: Int,
@SerialName("items_count") val itemsCount: Int,
@SerialName("icon_url") @Serializable(URISerializer::class) val iconUrl: URI
) {
constructor(id: TagId, followersCount: Int, iconUrl: URI, itemsCount: Int) :
this(id.value, followersCount, itemsCount, iconUrl)
val id get() = TagId(_id)
enum class Sort {
COUNT, NAME;
val key = name.toLowerCase(Locale.getDefault())
}
}
object URISerializer : KSerializer<URI> {
override val descriptor: SerialDescriptor =
PrimitiveDescriptor("URISerializer", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): URI = URI.create(decoder.decodeString())
override fun serialize(encoder: Encoder, value: URI) = encoder.encodeString(value.toString())
}
テスト
HackTest.kt
val tag = Tag(TagId("this is tag"), 101, URI.create("https://example.com"), 4502)
val json = Json.stringify(Tag.serializer(), tag)
println(json)
val parsedTag = Json.parse(QiitaTag.serializer(), json)
println("$tag")
println("id: ${tag.id}"}
json = {"tag_id":"this is tag","followers_count":101,"items_count":4502,"icon_url":"https://example.com"}
tag = Tag(_id=this is tag, followersCount=101, itemsCount=4502, iconUrl=https://example.com)
id: QiitaTagId(value=this is tag)
ポイント
・inline class
が使えないのでプライベートコンストラクタでプリミティブにしてを定義
・セカンドコンストラクタでinline class
を使用して定義
・プライマリ、セカンド コンストラクタで同じ引数順序は使用できないので入れ替える
・idのgetterを作成する
おわり
ハックと言われるものではないと思う、、、
将来的にサポートされるので多分、待つのもありかなと。
既出でしたらすみません。見つけられませんでした。
エラー等ありましたらコメントお願いします。