Kotlin Serialization ガイド　第2章 ビルトインクラス

#はじめに
　[Kotlin Serialization ガイドの目次](https://qiita.com/guijiu/items/097e858e4930b6d7e6c0)に基づいて「[Kotlin Serialization guide](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serialization-guide.md#kotlin-serialization-guide)」を訳しています。
　なお、翻訳には[DeepL](https://www.deepl.com/translator)の力を９９％借りています。
　もし、一緒に「[Kotlin Serialization ガイド](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serialization-guide.md#kotlin-serialization-guide)」の翻訳をして下さる方がいらっしゃいましたら、コメント欄などから連絡をください。

##第2章 ビルトインクラス＜[原文](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/builtin-classes.md#builtin-classes)＞
Latest commit 728e220 on 24 Nov 2020版

　[Kotlin Serialization Guide](serialization-guide.md)の第2章です。　すべてのプリミティブ型と文字列に加えて、標準コレクションを含むKotlin標準ライブラリの一部のクラスのシリアライズがKotlin Serializationに組み込まれています。この章ではその詳細を説明します。

<!--- TEST_NAME BuiltinClassesTest -->

**目次**

<!--- TOC -->

* [プリミティブ](#プリミティブ)
  * [数字](#数字)
  * [Long型数字](#Long型数字)
  * [文字列としてのLong型数字](#文字列としてのLong型数字)
  * [列挙型クラス](#列挙型クラス)
  * [列挙エントリのシリアル名](#列挙エントリのシリアル名)
* [コンポジット](#コンポジット)
  * [ペアとトリプル](#ペアとトリプル)
  * [リスト](#リスト)
  * [セットとその他のコレクション](#セットとその他のコレクション)
  * [コレクションのデシリアライズ](#コレクションのデシリアライズ)
  * [マップ](#マップ)
  * [ユニットオブジェクトとシングルトンオブジェクト](#ユニットオブジェクトとシングルトンオブジェクト)

<!--- END -->

<!--- INCLUDE .*-builtin-.*
import kotlinx.serialization.*
import kotlinx.serialization.json.*
-->

## プリミティブ

　Kotlin Serializationには次の10種類のプリミティブの型があります。
　　　　`Boolean`, `Byte`, `Short`, `Int`, `Long`, `Float`, `Double`, `Char`, `String`, そして列挙型(`enums`)
　そしてこの他に、これらプリミティブな型の組み合わせで構成された型があります。

### 数字

　すべてのタイプの整数と浮動小数点のKotlin数をシリアライズすることができます。

<!--- INCLUDE
import kotlin.math.*
-->

```kotlin
@Serializable
class Data(
    val answer: Int,
    val pi: Double
)                     

fun main() {
    val data = Data(42, PI)
    println(Json.encodeToString(data))
}
```                                   

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-01.kt)から取得できます。

JSONでの自然な表現が使われています。

```text
{"answer":42,"pi":3.141592653589793}
```

<!--- TEST -->

> 実験的な符号なし数字やその他の実験的なインラインクラスは、Kotlin Serializationではまだサポートされていません。


### Long型数字

長い整数も直列化できます。

```kotlin                
@Serializable
class Data(val signature: Long)

fun main() {
    val data = Data(0x1CAFE2FEED0BABE0)
    println(Json.encodeToString(data))
}
``` 

> 完全なコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-02.kt)から取得できます。

デフォルトでは、数値としてJSONにシリアライズされます。

```text
{"signature":2067120338512882656}
```

<!--- TEST -->

### 文字列としてのLong型数字

　先ほどの例で出力されたJSONは、Kotlin/JS上で実行されているKotlin Serializationによって正常にデコードされます。しかし、このJSONをJavaScriptのネイティブメソッドでパースしようとすると、このように切り詰められた結果が得られます。

```
JSON.parse("{\"signature\":2067120338512882656}")
▶ {signature: 2067120338512882700} 
```

　Kotlin Longの完全な範囲はJavaScriptの数値に収まらないため、その精度はJavaScriptで失われてしまいます。一般的な回避策は、JSON の文字列型を使って完全な精度で長い数値を表現することです。このアプローチは、Kotlin の [`LongAsStringSerializer`](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization.builtins/-long-as-string-serializer/index.html) によるシリアライズによってオプションでサポートされており、[`@Serializable`](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html) アノテーションを使って指定することができます。

<!--- INCLUDE
import kotlinx.serialization.builtins.*
-->

```kotlin                
@Serializable
class Data(
    @Serializable(with=LongAsStringSerializer::class)
    val signature: Long
)

fun main() {
    val data = Data(0x1CAFE2FEED0BABE0)
    println(Json.encodeToString(data))
}
``` 

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-03.kt)から取得できます。

　このJSONはJavaScriptでネイティブに解析され、精度を損なうことなく解析されます。

```text
{"signature":"2067120338512882656"}
```                                         

> 「[ファイルにシリアライザを指定する](https://qiita.com/guijiu/items/be7fa14c49cb7e3006dd#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E3%82%92%E6%8C%87%E5%AE%9A)」のセクションでは、`LongAsStringSerializer` のようなシリアライザをファイル内のすべてのプロパティに指定する方法を説明します。


<!--- TEST -->

### 列挙型クラス

　以下の例に示すように、すべての列挙型クラスは `@Serializable` をマークしなくても、すぐにシリアライズ可能です。


```kotlin          
// @Serializable annotation is not need for a enum classes
enum class Status { SUPPORTED }
        
@Serializable
class Project(val name: String, val status: Status) 

fun main() {
    val data = Project("kotlinx.serialization", Status.SUPPORTED)
    println(Json.encodeToString(data))
}
```                                        

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-04.kt)から取得することができます。

　JSONではenumは文字列としてエンコードされます。

```text
{"name":"kotlinx.serialization","status":"SUPPORTED"}
```   

<!--- TEST -->

### 列挙エントリのシリアル名

　enumエントリのシリアル名は、[シリアルフィールド名](https://qiita.com/guijiu/items/4defa057b800a2348607#%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E5%90%8D)のセクションのプロパティに表示されているのと同じように、[SerialName](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html)アノテーションを使ってカスタマイズすることができます。ただし、この場合、列挙クラス全体には [`@Serializable`](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html) アノテーションを付けなければなりません。

```kotlin
@Serializable // required because of @SerialName
enum class Status { @SerialName("maintained") SUPPORTED }
        
@Serializable
class Project(val name: String, val status: Status) 

fun main() {
    val data = Project("kotlinx.serialization", Status.SUPPORTED)
    println(Json.encodeToString(data))
}
```                                        

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-05.kt)から取得することができます。

　指定したシリアル名が結果のJSONで使用されるようになりました。

```text
{"name":"kotlinx.serialization","status":"maintained"}
```   

<!--- TEST -->

##コンポジット

　Kotlin Serializationでは、標準ライブラリにある多くのコンポジット型がサポートされています。

### ペアとトリプル

　Kotlin標準ライブラリのシンプルなデータクラス [Pair](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/) と [Triple](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-triple/) はシリアライズ可能です。

```kotlin
@Serializable
class Project(val name: String)

fun main() {
    val pair = 1 to Project("kotlinx.serialization")
    println(Json.encodeToString(pair))
}  
```                                

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-06.kt)から取得することができます。

```text
{"first":1,"second":{"name":"kotlinx.serialization"}}
```

<!--- TEST -->

> Kotlin標準ライブラリのすべてのクラスがシリアル化できるわけではありません。特にrangeと[Regex](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/)クラスは現在のところシリアライズできません。将来的にはシリアライズのサポートが追加されるかもしれません。 

### リスト 

　シリアライズ可能なクラスの[List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/)をシリアライズすることができます。

```kotlin
@Serializable
class Project(val name: String)

fun main() {
    val list = listOf(
        Project("kotlinx.serialization"),
        Project("kotlinx.coroutines")    
    )
    println(Json.encodeToString(list))
}  
```

> 完全なコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-07.kt)から取得できます。

　結果はJSONのリストとして表現されます。

```text
[{"name":"kotlinx.serialization"},{"name":"kotlinx.coroutines"}]
```     

<!--- TEST -->

### セットとその他のコレクション

[Set](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-set/)のような他のコレクションもシリアル化されています。

```kotlin
@Serializable
class Project(val name: String)

fun main() {
    val set = setOf(
        Project("kotlinx.serialization"),
        Project("kotlinx.coroutines")    
    )
    println(Json.encodeToString(set))
}  
```

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-08.kt)から取得することができます。

[Set](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-set/)も他のすべてのコレクションと同様にJSONではリストとして表現されます。

```text
[{"name":"kotlinx.serialization"},{"name":"kotlinx.coroutines"}]
```     

<!--- TEST -->

### コレクションのデシリアライズ

　デシリアライズの間、結果のオブジェクトの型は、ソースコードで指定された静的な型によって決定されます。次の例は、同じ JSON の整数リストを、異なる Kotlin 型の 2 つのプロパティにデシリアライズする方法を示しています。

```kotlin             
@Serializable
data class Data(
    val a: List<Int>,
    val b: Set<Int>
)
     
fun main() {
    val data = Json.decodeFromString<Data>("""
        {
            "a": [42, 42],
            "b": [42, 42]
        }
    """)
    println(data)
}
```    

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-09.kt)から取得できます。

　`data.b` プロパティは [Set](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-set/) なので、重複していた値が消えてしまいました。

```text
Data(a=[42, 42], b=[42])
```

<!--- TEST -->

### マップ

　プリミティブまたは列挙キーと任意の直列化可能な値を持つ[Map](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/)を直列化することができます。

```kotlin
@Serializable
class Project(val name: String)

fun main() {
    val map = mapOf(
        1 to Project("kotlinx.serialization"),
        2 to Project("kotlinx.coroutines")    
    )
    println(Json.encodeToString(map))
}  
```                                

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-10.kt)から取得することができます。

　JSON の Kotlin マップはオブジェクトとして表現されます。JSONではオブジェクトのキーは常に文字列であるため、Kotlinでは数字であってもキーは文字列としてエンコードされます。


```text
{"1":{"name":"kotlinx.serialization"},"2":{"name":"kotlinx.coroutines"}}
```

<!--- TEST -->

> キーを合成できないというのは、JSON 固有の制限です。[構造化マップのキーを許可する](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#allowing-structured-map-keys)のセクションで示されているように、解除することができます。


### ユニットオブジェクトとシングルトンオブジェクト

　Kotlin 組み込みの `Unit` 型もシリアライズ可能です。`ユニット`はKotlinの[シングルトンオブジェクト](https://kotlinlang.org/docs/tutorials/kotlin-for-py/objects-and-companion-objects.html)であり、他のKotlinオブジェクトと同じように扱われます。
　概念的には、シングルトンとはインスタンスが1つしかないクラスのことで、状態がオブジェクトを定義するのではなく、オブジェクトがその状態を定義することを意味します。JSONでは、オブジェクトは空の構造体としてシリアライズされます。

```kotlin
@Serializable
object SerializationVersion {
    val libraryVersion: String = "1.0.0"
}

fun main() {
    println(Json.encodeToString(SerializationVersion))
    println(Json.encodeToString(Unit))
}  
```                                

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-builtin-11.kt)から取得することができます。

　一見無駄に見えるかもしれませんが、これは、[Polymorphism.Objects](https://qiita.com/guijiu/items/b177808b03b59f76c8ee#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)のセクションで説明されているように、密閉されたクラスのシリアライズを行う際に便利です。

```text
{}
{}
```

<!--- TEST -->

> オブジェクトのシリアライズはフォーマット固有のものです。他のフォーマットでは、オブジェクトの完全修飾名を使用するなど、オブジェクトの表現方法が異なる場合があります。

---

　次の章では、[シリアライザ](https://qiita.com/guijiu/items/be7fa14c49cb7e3006dd#%E7%AC%AC3%E7%AB%A0-%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6-%E5%8E%9F%E6%96%87)を取り上げます。

<!-- stdlib references -->
[Double.NaN]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/-na-n.html
[Pair]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/ 
[Triple]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-triple/ 
[Regex]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/
[List]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/ 
[Set]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-set/ 
[Map]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/ 

<!--- MODULE /kotlinx-serialization-core -->
<!--- INDEX kotlinx-serialization-core/kotlinx.serialization -->
[Serializable]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html
[SerialName]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html
<!--- MODULE /kotlinx-serialization-core -->
<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.builtins -->
[LongAsStringSerializer]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization.builtins/-long-as-string-serializer/index.html
<!--- END -->