Kotlin Serialization ガイド　第５章 JSONの機能

#はじめに
　[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)」の翻訳をして下さる方がいらっしゃいましたら、コメント欄などから連絡をください。

# 第５章　JSONの機能＜[原文](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#json-features)＞

<!--- TEST_NAME JsonTest -->

Latest commit 728e220 on 24 Nov 2020版

[Kotlin Serialization Guide](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serialization-guide.md)の第5章です。
この章では、さまざまな [Json](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/index.html) の機能について解説します。

**目次**

<!--- TOC -->

* [Jsonの設定](#jsonの設定)
  * [綺麗な印刷](#綺麗な印刷)
  * [簡潔な構文解析](#簡潔な構文解析)
  * [未知のキーを無視](#未知のキーを無視)
  * [入力値の強制](#入力値の強制)
  * [エンコードのデフォルト値](#エンコードのデフォルト値)
  * [構造化されたマップキーの使用許可](#構造化されたマップキーの使用許可)
  * [特殊な浮動小数点値の許可](#特殊な浮動小数点値の許可)
  * [クラス判別器](#クラス判別器)
* [Json要素](#json要素)
  * [Json要素への構文解析](#json要素への構文解析)
  * [Json要素のサブタイプ](#json要素のサブタイプ)
  * [Json要素ビルダー](#json-要素のビルダー)
  * [Json要素のデコード](#json要素のデコード)
* [Jsonの変換](#json変換)
  * [配列の折り返し(ラッピング)](#配列の折り返しラッピング)
  * [配列の展開(アンラッピング)](#配列の展開アンラッピング)
  * [デフォルト値の操作](#デフォルト値の操作)
  * [コンテンツベースのポリモーフィックの逆シリアライゼーション](#コンテンツベースのポリモーフィックの逆シリアライゼーション)
  * [フード下（実験的なもの）](#フード下実験的なもの)
  * [カスタムJSON属性の維持](#カスタムjson属性の維持)

<!--- END -->

## Jsonの設定

　デフォルトでは、[Json](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/index.html)の実装は無効な入力に対して非常に厳しく、Kotlinの型の安全性を確保しています。はシリアライズできるKotlinの値を制限し、結果として得られるJSON表現が標準的なものになるようにします。多くの非標準JSON機能は、JSON _format_のカスタムインスタンスを作成することでサポートされています。デフォルトでは、[Json]の実装は無効な入力に対してかなり厳しく、Kotlinの型の安全性を強制し、シリアライズできるKotlinの値を制限して、結果として得られるJSON表現が標準的なものになるようにしています。多くの非標準のJSON機能は、JSON _format_のカスタムインスタンスを作成することでサポートされています。

　JSON形式の設定は、デフォルトの `Json` オブジェクトや [Json()] ビルダー関数など、既存のインスタンスを利用して独自の [Json]クラスのインスタンスを作成することで指定することができます。追加のパラメータは[JsonBuilder] DSLを介してブロックで指定します。結果として得られる `Json` 形式のインスタンスは不変でスレッドセーフです。これは単にトップレベルのプロパティに格納することができます。

> パフォーマンス上の理由から、フォーマットのカスタムインスタンスを保存して再利用することを推奨します。

　この章では、[Json]がサポートする様々な設定機能を紹介します。　

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

### 綺麗な印刷

　JSONは、[prettyPrint](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FprettyPrint%2F%23%2FPointingToDeclaration%2F)プロパティを設定することで、出力をきれいに印刷するように設定することができます。

```kotlin
val format = Json { prettyPrint = true }

@Serializable 
data class Project(val name: String, val language: String)

fun main() {                                      
    val data = Project("kotlinx.serialization", "Kotlin")
    println(format.encodeToString(data))
}
```

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

　以下のような良い結果が得られます。

```text 
{
    "name": "kotlinx.serialization",
    "language": "Kotlin"
}
``` 

<!--- TEST -->


### 簡潔な構文解析

　デフォルトでは、[Json]パーサは、できるだけ仕様に準拠するように、様々なJSONの制限を強制します（[RFC-4627]を参照してください）。キーは引用符で囲まなければならず、リテラルは引用符で囲まれていないものとする。これらの制限は、 [isLenient](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FisLenient%2F%23%2FPointingToDeclaration%2F) プロパティで緩和することができます。`isLenient = true` とすると、かなり自由なフォーマットのデータを解析することができます。


```kotlin
val format = Json { isLenient = true }

enum class Status { SUPPORTED }                                                     

@Serializable 
data class Project(val name: String, val status: Status, val votes: Int)
    
fun main() {             
    val data = format.decodeFromString<Project>("""
        { 
            name   : kotlinx.serialization,
            status : SUPPORTED,
            votes  : "9000"
        }
    """)
    println(data)
}
```                                  

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

　整数が引用符で囲まれていたのに、キー、文字列、enumの値がすべて引用符で囲まれていないのに、オブジェクトを取得しています。

```text
Project(name=kotlinx.serialization, status=SUPPORTED, votes=9000)
``` 

<!--- TEST -->

### 未知のキーを無視

　JSON形式は、サードパーティのサービスの出力を読み取るためによく使用されますが、そうでなければ、APIの進化の一環として新しいプロパティが追加される可能性があるような、非常にダイナミックな環境でも使用されます。デフォルトでは、デシリアライズ中に未知のキーが検出されるとエラーが発生します。この動作は、[ignoreUnknownKeys](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FignoreUnknownKeys%2F%23%2FPointingToDeclaration%2F)プロパティで設定できます。

```kotlin
val format = Json { ignoreUnknownKeys = true }
@Serializable 
data class Project(val name: String)
    
fun main() {             
    val data = format.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","language":"Kotlin"}
    """)
    println(data)
}
```                                  

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

　これはオブジェクトが `language` プロパティを欠いているにもかかわらず、オブジェクトをデコードします。

```text
Project(name=kotlinx.serialization)
``` 

<!--- TEST -->

### 入力値の強制

　野生(wild)で遭遇するJSONフォーマットは、型の面で柔軟性があり、すぐに進化することができます。これは、実際の値が期待値と一致しない場合に、デコード中に例外が発生する可能性があります。デフォルトでは、[Json] の実装は、[型安全性の確保](https://qiita.com/guijiu/items/4defa057b800a2348607#%E5%9E%8B%E5%AE%89%E5%85%A8%E6%80%A7%E3%81%AE%E7%A2%BA%E4%BF%9D) のセクションで実証されたように、入力型に関しては厳格です。これは [coerceInputValues](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FcoerceInputValues%2F%23%2FPointingToDeclaration%2F) プロパティを使用して多少緩和することができます。　このプロパティは、デコードにのみ影響します。これは、無効な入力値の限られたサブセットを、対応するプロパティがないかのように扱い、代わりに対応するプロパティのデフォルト値を使用します。
　現在サポートされている無効な値のリストは以下の通りです。

* NULL不可能な型のための `null` 入力。
* 列挙型の値が不明です。

> このリストは将来的に拡張される可能性があり、このプロパティで設定された[Json]インスタンスは、入力中の無効な値に対してさらに寛容になり、それらをデフォルト値に置き換えるようになります。   


　ここでは、[型安全性の確保](https://qiita.com/guijiu/items/4defa057b800a2348607#%E5%9E%8B%E5%AE%89%E5%85%A8%E6%80%A7%E3%81%AE%E7%A2%BA%E4%BF%9D)の部分を例にしてみます。

```kotlin
val format = Json { coerceInputValues = true }

@Serializable 
data class Project(val name: String, val language: String = "Kotlin")

fun main() {
    val data = format.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","language":null}
    """)
    println(data)
}
```                                  

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

　これにより、`language` プロパティの無効な `null` 値がデフォルト値に強制的に変換されたことがわかります。

```text
Project(name=kotlinx.serialization, language=Kotlin)
```    

<!--- TEST -->

### エンコードのデフォルト値

　プロパティのデフォルト値はデフォルトではエンコードされていません。詳細は、[デフォルトがエンコードされていない](https://qiita.com/guijiu/items/4defa057b800a2348607#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E5%80%A4%E3%81%AF%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84)の項を参照してください。これは、NULLデフォルトを持つNULL可能なプロパティに対して特に有用であり、対応するNULL値の書き込みを避けることができます。デフォルトの動作は、[encodeDefaults](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FencodeDefaults%2F%23%2FPointingToDeclaration%2F)プロパティで変更できます。

```kotlin
val format = Json { encodeDefaults = true }

@Serializable 
class Project(
    val name: String, 
    val language: String = "Kotlin",
    val website: String? = null
)           

fun main() {
    val data = Project("kotlinx.serialization")
    println(format.encodeToString(data))
}
```                                  

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

　これは、すべてのプロパティの値をエンコードした以下の出力を生成します。

```text
{"name":"kotlinx.serialization","language":"Kotlin","website":null}
```                 

<!--- TEST -->

### 構造化されたマップキーの使用許可

　JSONフォーマットは、構造化されたキーを持つマップの概念をネイティブにサポートしていません。JSON オブジェクトのキーは文字列であり、デフォルトではプリミティブや列挙型のみを表現するために使用することができます。JSON フォーマットは、構造化されたキーを持つマップの概念をネイティブにサポートしていません。JSON オブジェクトのキーは文字列であり、デフォルトではプリミティブや列挙型のみを表現するために使用することができます。

　構造化キーの非標準サポートは、[allowStructuredMapKeys][JsonBuilder.allowStructuredMapKeys]プロパティを使用して有効にすることができます。


```kotlin
val format = Json { allowStructuredMapKeys = true }

@Serializable 
data class Project(val name: String)
    
fun main() {             
    val map = mapOf(
        Project("kotlinx.serialization") to "Serialization",
        Project("kotlinx.coroutines") to "Coroutines"
    )
    println(format.encodeToString(map))
}
```                                  

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

　構造化キーを持つマップは `[key1, value1, key2, value2,...]` のJSON配列として表現されます。

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

<!--- TEST -->           

### 特殊な浮動小数点値の許可

　デフォルトでは、JSON仕様では禁止されているため、[Double.NaN]や無限大などの特殊な浮動小数点値はJSONではサポートされていません。しかし、[allowSpecialFloatingPointValues](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FallowSpecialFloatingPointValues%2F%23%2FPointingToDeclaration%2F)プロパティを使用して有効にすることができます。

```kotlin       
val format = Json { allowSpecialFloatingPointValues = true }

@Serializable
class Data(
    val value: Double
)                     

fun main() {
    val data = Data(Double.NaN)
    println(format.encodeToString(data))
}
```                                   

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

　この例では、以下のような非標準のJSON出力を生成していますが、JVMの世界では特殊な値のために広く使われているエンコーディングです。

```text
{"value":NaN}
```   

<!--- TEST -->

### クラス判別器

　多相データを持っているときに型を指定するキー名は、[classDiscriminator](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FclassDiscriminator%2F%23%2FPointingToDeclaration%2F)プロパティで指定することができます。

```kotlin        
val format = Json { classDiscriminator = "#class" }

@Serializable
sealed class Project {
    abstract val name: String
}
            
@Serializable         
@SerialName("owned")
class OwnedProject(override val name: String, val owner: String) : Project()

fun main() {
    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
    println(format.encodeToString(data))
}  
```

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

　クラスの明示的に指定された [SerialName] と組み合わせることで、結果として得られる JSON オブジェクトを完全に制御することができます。

```text 
{"#class":"owned","name":"kotlinx.coroutines","owner":"kotlin"}
```                   

<!--- TEST -->

## Json要素

　これまでは、オブジェクトを文字列に変換したり戻したりしてJSON形式を扱ってきました。しかし、JSONは実際には非常に柔軟性に富んでいることが多く、このような構造化されていないデータを扱う場合は、Kotlinのシリアライズというタイプセーフの世界にはなかなか馴染まないため、パースなどの作業をする前にデータを微調整する必要があるかもしれません。

### Json要素への構文解析

　文字列は、[Json.parseToJsonElement]関数で[JsonElement]のインスタンスに解析することができます。デコードもデシリアライズもしない、というのは、その過程で何も起こらないからです。ここではJSONパーサー(構文解析）のみを使用しています。 

```kotlin
fun main() {
    val element = Json.parseToJsonElement("""
        {"name":"kotlinx.serialization","language":"Kotlin"}
    """)
    println(element)
}
```

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

　JsonElement` はそれ自身を有効なJSONとして表示します。

```text 
{"name":"kotlinx.serialization","language":"Kotlin"}
```
    
<!--- TEST -->

### Json要素のサブタイプ

　[JsonElement](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html)クラスは、JSON文法に密接に従った3つの直接的なサブタイプを持っています。

* [JsonPrimitive](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html)は、文字列、数値、ブール値、ヌル値など、すべてのプリミティブなJSON要素を表します。各プリミティブには、単純な文字列[content][JsonPrimitive.content]があります。また、様々なKotlinプリミティブ型を受け入れて `JsonPrimitive` に変換するためにオーバーロードされた [JsonPrimitive()](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive.html)コンストラクタ関数もあります。

* [JsonArray] は JSON `[....]` の配列を表す。JsonElement`のKotlinの[List]である。
* [JsonObject] は JSON の `{...}` オブジェクトを表す。これは、`String` キーから `JsonElement` 値へのKotlinの[Map]である。

　JsonElement` クラスは `jsonXxx` の拡張子を持ち、それを対応するサブタイプ ( [jsonPrimitive](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html#kotlinx.serialization.json%2F%2FjsonPrimitive%2Fkotlinx.serialization.json.JsonElement%23%2FPointingToDeclaration%2F), [jsonArray](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html#kotlinx.serialization.json%2F%2FjsonArray%2Fkotlinx.serialization.json.JsonElement%23%2FPointingToDeclaration%2F), [jsonObject](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html#kotlinx.serialization.json%2F%2FjsonObject%2Fkotlinx.serialization.json.JsonElement%23%2FPointingToDeclaration%2F) ) にキャストします。

　`JsonPrimitive`クラスには、Kotlinのプリミティブ型([int], [intOrNull], [long], [longOrNull]など)への便利な変換器があり、構造を知っているJSONを使って流暢なコードを書くことができます。

```kotlin
fun main() {
    val element = Json.parseToJsonElement("""
        {
            "name": "kotlinx.serialization",
            "forks": [{"votes": 42}, {"votes": 9000}, {}]
        }
    """)
    val sum = element
        .jsonObject["forks"]!!
        .jsonArray.sumOf { it.jsonObject["votes"]?.jsonPrimitive?.int ?: 0 }
    println(sum)
}
```

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

　上の例では、`forks` 配列内のすべてのオブジェクトの `votes` を合計しています。

```text 
9042
```                 

<!--- TEST -->

### Json 要素のビルダー

　特定の[JsonElement](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html)サブタイプのインスタンスは、それぞれのビルダー関数[buildJsonArray](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/build-json-array.html)と[buildJsonObject](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/build-json-object.html)を用いて構築することができます。これはKotlin標準のライブラリ・コレクション・ビルダーに似ていますが、JSON固有の利便性である型固有のオーバーロードや内部ビルダー関数を追加した構造を定義するDSLを提供します。以下の例は、すべての主要な機能を示しています。 

```kotlin
fun main() {
    val element = buildJsonObject {
        put("name", "kotlinx.serialization")
        putJsonObject("owner") {
            put("name", "kotlin")
        }
        putJsonArray("forks") {
            addJsonObject {
                put("votes", 42)
            }
            addJsonObject {
                put("votes", 9000)
            }
        }
    }
    println(element)
}
```

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

　最後に、適切なJSON文字列を取得します。

```text 
{"name":"kotlinx.serialization","owner":{"name":"kotlin"},"forks":[{"votes":42},{"votes":9000}]}
```    

<!--- TEST -->

### Json要素のデコード

　[JsonElement](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html) クラスのインスタンスは、[Json.decodeFromJsonElement](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/decode-from-json-element.html) 関数を使ってシリアライズ可能なオブジェクトにデコードすることができます。

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

fun main() {
    val element = buildJsonObject {
        put("name", "kotlinx.serialization")
        put("language", "Kotlin")
    }
    val data = Json.decodeFromJsonElement<Project>(element)
    println(data)
}
```

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

　期待通りの結果になっています。

```text 
Project(name=kotlinx.serialization, language=Kotlin)
``` 

<!--- TEST -->

## Json変換

　シリアライズ後のJSON出力の形状や内容に影響を与えたり、入力をデシリアライズに適応させたりするには、[カスタムシリアライザー](https://qiita.com/guijiu/items/be7fa14c49cb7e3006dd#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6)を記述することが可能です。しかし、[Encoder] と [Decoder]の呼び出し規則に注意して従うことは、特に比較的小さくて簡単な作業の場合には便利ではないかもしれません。そのために、Kotlinのシリアライズでは、カスタムシリアライザを実装する際の負担を、Jsonの要素ツリーを操作する問題にまで軽減できるAPIを提供しています。

　カスタムシリアライザがどのようにクラスにバインドされるかなどについて説明しているので、[シリアライザ](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)の章に精通しておくことを強くお勧めします。

　変換機能は、[KSerializer]を実装した抽象的な[JsonTransformingSerializer]クラスによって提供されます。このクラスは、`Encoder`や`Decoder`と直接対話する代わりに、`transformSerialize`や`transformDeserialize`メソッドを使って、[JsonElement]クラスで表現されるJSONツリーの変換を依頼します。例を見てみましょう。

### 配列の折り返し(ラッピング)

　最初の例は、リストのJSON配列ラッピングを独自に実装したものです。`User` オブジェクトの JSON 配列を返す REST API を考えてみましょう。データモデルでは、`users.List<User>` プロパティにカスタムシリアライザを指定するために、[`@Serializable`][Serializable] アノテーションを使用しています。List<User>` プロパティを使用します。 

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

```kotlin 
@Serializable 
data class Project(
    val name: String,
    @Serializable(with = UserListSerializer::class)      
    val users: List<User>
)

@Serializable
data class User(val name: String)
```

　今のところ、我々はデシリアライズのみに関心があるので、`UserListSerializer`を実装し、`transformDeserialize`関数のみをオーバーライドします。JsonTransformingSerializer` のコンストラクタはオリジナルのシリアライザをパラメータとして受け取り、ここでは [コレクションシリアライザを構築](https://qiita.com/guijiu/items/be7fa14c49cb7e3006dd#%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E3%82%92%E6%A7%8B%E7%AF%89) のセクションのアプローチを利用して作成します。 

```kotlin
object UserListSerializer : JsonTransformingSerializer<List<User>>(ListSerializer(User.serializer())) {
    // If response is not an array, then it is a single object that should be wrapped into the array
    override fun transformDeserialize(element: JsonElement): JsonElement =
        if (element !is JsonArray) JsonArray(listOf(element)) else element
}
```

　これで、JSON 配列や単一の JSON オブジェクトを入力としてコードをテストすることができるようになりました。

```kotlin 
fun main() {     
    println(Json.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","users":{"name":"kotlin"}}
    """))
    println(Json.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","users":[{"name":"kotlin"},{"name":"jetbrains"}]}
    """))
}
```

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

　出力を見ると、両方のケースが正しくKotlin [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/)にデシリアライズされていることがわかります。

```text 
Project(name=kotlinx.serialization, users=[User(name=kotlin)])
Project(name=kotlinx.serialization, users=[User(name=kotlin), User(name=jetbrains)])
```  

<!--- TEST -->

### 配列の展開(アンラッピング)

　シリアライズ中に単一要素のリストを単一のJSONオブジェクトにアンラップするために `transformSerialize` 関数を実装することもできます。

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

@Serializable 
data class Project(
    val name: String,
    @Serializable(with = UserListSerializer::class)      
    val users: List<User>
)

@Serializable
data class User(val name: String)

object UserListSerializer : JsonTransformingSerializer<List<User>>(ListSerializer(User.serializer())) {
-->

```kotlin
    override fun transformSerialize(element: JsonElement): JsonElement {
        require(element is JsonArray) // we are using this serializer with lists only
        return element.singleOrNull() ?: element
    }
```

<!--- INCLUDE
}
-->

　さて、Kotlinでオブジェクトの単一要素のリストから始める。

```kotlin 
fun main() {     
    val data = Project("kotlinx.serialization", listOf(User("kotlin")))
    println(Json.encodeToString(data))
}
```

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

　結局、1つのJSONオブジェクトになってしまいます。

```text 
{"name":"kotlinx.serialization","users":{"name":"kotlin"}}
```  

<!--- TEST -->

### デフォルト値の操作

　もう一つの有用な変換の種類は、出力JSONから特定の値を省略することです。例えば、欠落している場合やその他のドメイン固有の理由でデフォルトとして扱われるためです。例えば、`Project` データモデルでは `language` プロパティにデフォルト値を指定できないが、`Kotlin` と等しい場合には JSON から省略しなければならないとします (いずれにせよ Kotlin がデフォルトであるべきであることは誰もが認めるところです)。`Project`クラス用の[プラグイン生成ジェネリックシリアライザ](https://qiita.com/guijiu/items/be7fa14c49cb7e3006dd#%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E7%94%9F%E6%88%90%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AA%E3%83%83%E3%82%AF%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6)をベースにした特別な`ProjectSerializer`を記述することで修正する。

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

object ProjectSerializer : JsonTransformingSerializer<Project>(Project.serializer()) {
    override fun transformSerialize(element: JsonElement): JsonElement =
        // Filter out top-level key value pair with the key "language" and the value "Kotlin"
        JsonObject(element.jsonObject.filterNot {
            (k, v) -> k == "language" && v.jsonPrimitive.content == "Kotlin"
        })
}                           
```

　以下の例では、`Project`クラスをトップレベルでシリアライズしているので、[シリアライザを手動で渡す](https://qiita.com/guijiu/items/be7fa14c49cb7e3006dd#%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E3%82%92%E6%89%8B%E5%8B%95%E3%81%A7%E6%B8%A1%E3%81%99)で示したように、上記の`ProjectSerializer`を明示的に[Json.encodeToString]関数に渡しています。  

```kotlin
fun main() {
    val data = Project("kotlinx.serialization", "Kotlin")
    println(Json.encodeToString(data)) // using plugin-generated serializer
    println(Json.encodeToString(ProjectSerializer, data)) // using custom serializer
}
```

> フルコードは[こちら](https://github.com/Kotlin/kotlinx.serialization/blob/master/guide/example/example-json-15.kt)から取得することができます。カスタムシリアライザの効果がよくわかります。

```text 
{"name":"kotlinx.serialization","language":"Kotlin"}
{"name":"kotlinx.serialization"}
```

<!--- TEST -->

### コンテンツベースのポリモーフィックの逆シリアライゼーション

　通常、[ポリモフィズムおけるシリアル化](https://qiita.com/guijiu/items/b177808b03b59f76c8ee#%E7%AC%AC4%E7%AB%A0%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0%E5%8E%9F%E6%96%87)では、Kotlinクラスをデシリアライズするために使用されるべき実際のシリアライザを決定するために、JSONオブジェクトに専用の`"type`キー(クラス判別キーとしても知られています)が必要になります。
　しかし、入力にtypeプロパティが存在しない場合もあり、特定のキーの存在などJSONの形状から実際の型を推測することが期待されます。
　[JsonContentPolymorphicSerializer]は、そのような戦略のためのスケルトン実装を提供します。これを使うには、`selectDeserializer`メソッドをオーバーライドする。まずは以下のようなクラス階層から見ていきましょう。

> 注:[シールドされたクラス](https://qiita.com/guijiu/items/b177808b03b59f76c8ee#%E3%82%B7%E3%83%BC%E3%83%AB%E3%83%89%E3%81%95%E3%82%8C%E3%81%9F%E3%82%AF%E3%83%A9%E3%82%B9) のセクションで推奨されているように `シールドされている`必要はありません。なぜなら、適切なサブクラスを自動的に選択するプラグイン生成コードを利用するのではなく、このコードを手動で実装しようとしているからです。

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

```kotlin
@Serializable
abstract class Project {
    abstract val name: String
}                   

@Serializable 
data class BasicProject(override val name: String): Project() 
            
@Serializable
data class OwnedProject(override val name: String, val owner: String) : Project()
```

　JSONオブジェクトに `owner` キーがあることで `BasicProject` と `OwnedProject` のサブクラスを区別したいと思います。

```kotlin
object ProjectSerializer : JsonContentPolymorphicSerializer<Project>(Project::class) {
    override fun selectDeserializer(element: JsonElement) = when {
        "owner" in element.jsonObject -> OwnedProject.serializer()
        else -> BasicProject.serializer()
    }
}
```

　このようなシリアライザでデータをシリアライズすることができます。その場合、実行時には[登録されたもの(registered)] (https://qiita.com/guijiu/items/b177808b03b59f76c8ee#%E7%99%BB%E9%8C%B2%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B5%E3%83%96%E3%82%AF%E3%83%A9%E3%82%B9)か、実際の型に合わせたデフォルトのシリアライザが選択されます。

```kotlin 
fun main() {
    val data = listOf(
        OwnedProject("kotlinx.serialization", "kotlin"),
        BasicProject("example")
    )
    val string = Json.encodeToString(ListSerializer(ProjectSerializer), data)
    println(string)
    println(Json.decodeFromString(ListSerializer(ProjectSerializer), string))
}
```

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

　JSON出力にはクラス判別器は追加されていません。

```text
[{"name":"kotlinx.serialization","owner":"kotlin"},{"name":"example"}]
[OwnedProject(name=kotlinx.serialization, owner=kotlin), BasicProject(name=example)]
```     

<!--- TEST -->

### フード下（実験的なもの）

　上記の抽象シリアライザはほとんどのケースをカバーすることができますが、[KSerializer]クラスのみを使用して、同様の機械を手動で実装することも可能です。抽象メソッド `transformSerialize`/`transformDeserialize`/`selectDeserializer` を微調整するだけでは不十分な場合は、`serialize`/`deserialize`を変更するのがよいでしょう。[Json]を使ったカスタムシリアライザに関する豆知識がいくつかあります。

* 現在のフォーマットが[Json]の場合、[Encoder]を[JsonEncoder]に、[Decoder]を[JsonDecoder]にキャストすることができます。
* `JsonDecoder` は [decodeJsonElement][JsonDecoder.decodeJsonElement] メソッドを、`JsonEncoder` は [encodeJsonElement][JsonEncoder.encodeJsonElement] メソッドを持つ。これは基本的にはストリーム内の現在の位置から、または現在の位置への要素の取得/挿入を行います。

* [`JsonDecoder`][JsonDecoder.json]と[`JsonEncoder`][JsonEncoder.json]の両方とも、現在使用中の設定をすべて含んだ[Json]インスタンスを返す `json` プロパティを持っています。

* [Json] には [encodeToJsonElement](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/encode-to-json-element.html) と [decodeFromJsonElement](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/decode-from-json-element.html) メソッドがあります。

　以上のことから、`Decoder -> JsonElement -> value` や `value -> JsonElement -> Encoder` の二段階変換を実装することが可能です。例えば、以下の `Response` クラスに対して完全なカスタムシリアライザを実装し、`Ok` サブクラスは直接表現し、`Error` サブクラスはエラーメッセージを持つオブジェクトで表現するようにします。

<!--- INCLUDE
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
-->

```kotlin     
@Serializable(with = ResponseSerializer::class)
sealed class Response<out T> {
    data class Ok<out T>(val data: T) : Response<T>()
    data class Error(val message: String) : Response<Nothing>()
}

class ResponseSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<Response<T>> {
    override val descriptor: SerialDescriptor = buildSerialDescriptor("Response", PolymorphicKind.SEALED) {
        element("Ok", buildClassSerialDescriptor("Ok") {
            element<String>("message")
        })
        element("Error", dataSerializer.descriptor)
    }

    override fun deserialize(decoder: Decoder): Response<T> {
        // Decoder -> JsonDecoder
        require(decoder is JsonDecoder) // this class can be decoded only by Json
        // JsonDecoder -> JsonElement
        val element = decoder.decodeJsonElement()
        // JsonElement -> value
        if (element is JsonObject && "error" in element)
            return Response.Error(element["error"]!!.jsonPrimitive.content)
        return Response.Ok(decoder.json.decodeFromJsonElement(dataSerializer, element))
    }

    override fun serialize(encoder: Encoder, value: Response<T>) {
        // Encoder -> JsonEncoder
        require(encoder is JsonEncoder) // This class can be encoded only by Json
        // value -> JsonElement
        val element = when (value) {
            is Response.Ok -> encoder.json.encodeToJsonElement(dataSerializer, value.data)
            is Response.Error -> buildJsonObject { put("error", value.message) }
        }
        // JsonElement -> JsonEncoder
        encoder.encodeJsonElement(element)
    }
}
```

　このシリアライズ可能な `Response` の実装で武装することで、シリアライズ可能なペイロードのデータを取得し、対応するレスポンスをシリアライズ/デシリアライズすることができます。

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

fun main() {
    val responses = listOf(
        Response.Ok(Project("kotlinx.serialization")),
        Response.Error("Not found")
    )
    val string = Json.encodeToString(responses)
    println(string)
    println(Json.decodeFromString<List<Response<Project>>>(string))
}
```

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

　これにより、JSON出力における `Response` クラスの表現を細かく制御することができます。

```text       
[{"name":"kotlinx.serialization"},{"error":"Not found"}]
[Ok(data=Project(name=kotlinx.serialization)), Error(message=Not found)]
```     

<!--- TEST -->

### カスタムJSON属性の維持

　カスタムJSON固有のシリアライザの良い例としては、未知のJSONプロパティをすべて`JsonObject`型の専用フィールドにパックするデシリアライザがあります。 基本的な `name` プロパティと任意の詳細をフラット化した `UnknownProject` &ndash; クラスを追加してみましょう。

<!--- INCLUDE
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
-->

```kotlin
data class UnknownProject(val name: String, val details: JsonObject)
```

　しかし、デフォルトのプラグイン生成シリアライザでは、詳細を別のJSONオブジェクトにする必要があり、それは私たちが望むものではありません。これを緩和するために、`Json` 形式でしか使えないという事実を利用した独自のシリアライザを書くことができます。

```kotlin
object UnknownProjectSerializer : KSerializer<UnknownProject> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("UnknownProject") {
        element<String>("name")
        element<JsonElement>("details")
    }

    override fun deserialize(decoder: Decoder): UnknownProject {
        // Cast to JSON-specific interface
        val jsonInput = decoder as? JsonDecoder ?: error("Can be deserialized only by JSON")
        // Read the whole content as JSON
        val json = jsonInput.decodeJsonElement().jsonObject
        // Extract and remove name property
        val name = json.getValue("name").jsonPrimitive.content
        val details = json.toMutableMap()
        details.remove("name")
        return UnknownProject(name, JsonObject(details))
    }

    override fun serialize(encoder: Encoder, value: UnknownProject) {
        error("Serialization is not supported")
    }
}
```

　これで、フラット化されたJSONの詳細を `UnknownProject` として読み込むことができるようになった。

```kotlin
fun main() {
    println(Json.decodeFromString(UnknownProjectSerializer, """{"type":"unknown","name":"example","maintainer":"Unknown","license":"Apache 2.0"}"""))
}
```  

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

```text
UnknownProject(name=example, details={"type":"unknown","maintainer":"Unknown","license":"Apache 2.0"})
```

<!--- TEST -->

---

　次の章では、[代替フォーマットとカスタムフォーマット(実験)](https://qiita.com/guijiu/items/9a312d54b20baffff3bf#%E7%AC%AC%EF%BC%96%E7%AB%A0%E4%BB%A3%E6%9B%BF%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E3%81%A8%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E5%AE%9F%E9%A8%93)を取り上げます。



<!-- references -->
[RFC-4627]: https://www.ietf.org/rfc/rfc4627.txt

<!-- stdlib references -->
[Double.NaN]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/-na-n.html
[List]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/ 
[Map]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/ 

<!--- MODULE /kotlinx-serialization-core -->
<!--- INDEX kotlinx-serialization-core/kotlinx.serialization -->
[SerialName]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html
[KSerializer]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-k-serializer/index.html
[Serializable]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html
<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.encoding -->
[Encoder]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization.encoding/-encoder/index.html
[Decoder]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx-serialization-core/kotlinx.serialization.encoding/-decoder/index.html
<!--- MODULE /kotlinx-serialization-json -->
<!--- INDEX kotlinx-serialization-json/kotlinx.serialization.json -->
[Json]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/index.html
[Json()]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json.html
[JsonBuilder]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html
[JsonBuilder.prettyPrint]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FprettyPrint%2F%23%2FPointingToDeclaration%2F
[JsonBuilder.isLenient]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FisLenient%2F%23%2FPointingToDeclaration%2F
[JsonBuilder.ignoreUnknownKeys]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FignoreUnknownKeys%2F%23%2FPointingToDeclaration%2F
[JsonBuilder.coerceInputValues]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FcoerceInputValues%2F%23%2FPointingToDeclaration%2F
[JsonBuilder.encodeDefaults]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FencodeDefaults%2F%23%2FPointingToDeclaration%2F
[JsonBuilder.allowStructuredMapKeys]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FallowStructuredMapKeys%2F%23%2FPointingToDeclaration%2F
[JsonBuilder.allowSpecialFloatingPointValues]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FallowSpecialFloatingPointValues%2F%23%2FPointingToDeclaration%2F
[JsonBuilder.classDiscriminator]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-builder/index.html#kotlinx.serialization.json%2FJsonBuilder%2FclassDiscriminator%2F%23%2FPointingToDeclaration%2F
[JsonElement]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html
[Json.parseToJsonElement]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/parse-to-json-element.html
[JsonPrimitive]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html
[JsonPrimitive.content]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html#kotlinx.serialization.json%2FJsonPrimitive%2Fcontent%2F%23%2FPointingToDeclaration%2F
[JsonPrimitive()]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive.html
[JsonArray]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-array/index.html
[JsonObject]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-object/index.html
[_jsonPrimitive]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html#kotlinx.serialization.json%2F%2FjsonPrimitive%2Fkotlinx.serialization.json.JsonElement%23%2FPointingToDeclaration%2F
[_jsonArray]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html#kotlinx.serialization.json%2F%2FjsonArray%2Fkotlinx.serialization.json.JsonElement%23%2FPointingToDeclaration%2F
[_jsonObject]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/index.html#kotlinx.serialization.json%2F%2FjsonObject%2Fkotlinx.serialization.json.JsonElement%23%2FPointingToDeclaration%2F
[int]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html#kotlinx.serialization.json%2F%2Fint%2Fkotlinx.serialization.json.JsonPrimitive%23%2FPointingToDeclaration%2F
[intOrNull]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html#kotlinx.serialization.json%2F%2FintOrNull%2Fkotlinx.serialization.json.JsonPrimitive%23%2FPointingToDeclaration%2F
[long]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html#kotlinx.serialization.json%2F%2Flong%2Fkotlinx.serialization.json.JsonPrimitive%23%2FPointingToDeclaration%2F
[longOrNull]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-primitive/index.html#kotlinx.serialization.json%2F%2FlongOrNull%2Fkotlinx.serialization.json.JsonPrimitive%23%2FPointingToDeclaration%2F
[buildJsonArray]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/build-json-array.html
[buildJsonObject]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/build-json-object.html
[Json.decodeFromJsonElement]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/decode-from-json-element.html
[JsonTransformingSerializer]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-transforming-serializer/index.html
[Json.encodeToString]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/encode-to-string.html
[JsonContentPolymorphicSerializer]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-content-polymorphic-serializer/index.html
[JsonEncoder]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-encoder/index.html
[JsonDecoder]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-decoder/index.html
[JsonDecoder.decodeJsonElement]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-decoder/decode-json-element.html
[JsonEncoder.encodeJsonElement]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-encoder/encode-json-element.html
[JsonDecoder.json]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-decoder/index.html#kotlinx.serialization.json%2FJsonDecoder%2Fjson%2F%23%2FPointingToDeclaration%2F
[JsonEncoder.json]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json-encoder/index.html#kotlinx.serialization.json%2FJsonEncoder%2Fjson%2F%23%2FPointingToDeclaration%2F
[Json.encodeToJsonElement]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-json/kotlinx-serialization-json/kotlinx.serialization.json/-json/encode-to-json-element.html
<!--- END -->