1 /*
2  * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.serialization.json
6 
7 import kotlinx.serialization.*
8 import kotlinx.serialization.encoding.*
9 import kotlinx.serialization.descriptors.*
10 
11 /**
12  * Decoder used by [Json] during deserialization.
13  * This interface can be used to inject desired behaviour into a serialization process of [Json].
14  *
15  * Typical example of the usage:
16  * ```
17  * // Class representing Either<Left|Right>
18  * sealed class Either {
19  *     data class Left(val errorMsg: String) : Either()
20  *     data class Right(val data: Payload) : Either()
21  * }
22  *
23  * // Serializer injects custom behaviour by inspecting object content and writing
24  * object EitherSerializer : KSerializer<Either> {
25  *     override val descriptor: SerialDescriptor = buildSerialDescriptor("package.Either", PolymorphicKind.SEALED) {
26  *          // ..
27  *      }
28  *
29  *     override fun deserialize(decoder: Decoder): Either {
30  *         val input = decoder as? JsonDecoder ?: throw SerializationException("This class can be decoded only by Json format")
31  *         val tree = input.decodeJsonElement() as? JsonObject ?: throw SerializationException("Expected JsonObject")
32  *         if ("error" in tree) return Either.Left(tree["error"]!!.jsonPrimitive.content)
33  *         return Either.Right(input.json.decodeFromJsonElement(Payload.serializer(), tree))
34  *     }
35  *
36  *     override fun serialize(encoder: Encoder, value: Either) {
37  *         val output = encoder as? JsonEncoder ?: throw SerializationException("This class can be encoded only by Json format")
38  *         val tree = when (value) {
39  *           is Either.Left -> JsonObject(mapOf("error" to JsonPrimitive(value.errorMsg)))
40  *           is Either.Right -> output.json.encodeToJsonElement(Payload.serializer(), value.data)
41  *         }
42  *         output.encodeJsonElement(tree)
43  *     }
44  * }
45  * ```
46  *
47  * ### Not stable for inheritance
48  *
49  * `JsonDecoder` interface is not stable for inheritance in 3rd party libraries, as new methods
50  * might be added to this interface or contracts of the existing methods can be changed.
51  * Accepting this interface in your API methods, casting [Decoder] to [JsonDecoder] and invoking its
52  * methods is considered stable.
53  */
54 public interface JsonDecoder : Decoder, CompositeDecoder {
55     /**
56      * An instance of the current [Json].
57      */
58     public val json: Json
59 
60     /**
61      * Decodes the next element in the current input as [JsonElement].
62      * The type of the decoded element depends on the current state of the input and, when received
63      * by [serializer][KSerializer] in its [KSerializer.serialize] method, the type of the token directly matches
64      * the [kind][SerialDescriptor.kind].
65      *
66      * This method is allowed to invoke only as the part of the whole deserialization process of the class,
67      * calling this method after invoking [beginStructure] or any `decode*` method will lead to unspecified behaviour.
68      * For example:
69      * ```
70      * class Holder(val value: Int, val list: List<Int>())
71      *
72      * // Holder deserialize method
73      * fun deserialize(decoder: Decoder): Holder {
74      *     // Completely okay, the whole Holder object is read
75      *     val jsonObject = (decoder as JsonDecoder).decodeJsonElement()
76      *     // ...
77      * }
78      *
79      * // Incorrect Holder deserialize method
80      * fun deserialize(decoder: Decoder): Holder {
81      *     // decode "value" key unconditionally
82      *     decoder.decodeElementIndex(descriptor)
83      *     val value = decode.decodeInt()
84      *     // Incorrect, decoder is already in an intermediate state after decodeInt
85      *     val json = (decoder as JsonDecoder).decodeJsonElement()
86      *     // ...
87      * }
88      * ```
89      */
decodeJsonElementnull90     public fun decodeJsonElement(): JsonElement
91 }
92