0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Kotlin hack where kotlinx.serialization supports inlineclass(kotlinx.serializationでinlineClassを使用するハック)

Last updated at Posted at 2020-03-28

はじめに

現時点(2020/3/28)では、kotlinx.serializationinline 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を作成する

おわり

ハックと言われるものではないと思う、、、
将来的にサポートされるので多分、待つのもありかなと。
既出でしたらすみません。見つけられませんでした。
エラー等ありましたらコメントお願いします。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?