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