xref: /aosp_15_r20/external/kotlinx.serialization/docs/polymorphism.md (revision 57b5a4a64c534cf7f27ac9427ceab07f3d8ed3d8)
1*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST_NAME PolymorphismTest -->
2*57b5a4a6SAndroid Build Coastguard Worker
3*57b5a4a6SAndroid Build Coastguard Worker# Polymorphism
4*57b5a4a6SAndroid Build Coastguard Worker
5*57b5a4a6SAndroid Build Coastguard WorkerThis is the fourth chapter of the [Kotlin Serialization Guide](serialization-guide.md).
6*57b5a4a6SAndroid Build Coastguard WorkerIn this chapter we'll see how Kotlin Serialization deals with polymorphic class hierarchies.
7*57b5a4a6SAndroid Build Coastguard Worker
8*57b5a4a6SAndroid Build Coastguard Worker**Table of contents**
9*57b5a4a6SAndroid Build Coastguard Worker
10*57b5a4a6SAndroid Build Coastguard Worker<!--- TOC -->
11*57b5a4a6SAndroid Build Coastguard Worker
12*57b5a4a6SAndroid Build Coastguard Worker* [Closed polymorphism](#closed-polymorphism)
13*57b5a4a6SAndroid Build Coastguard Worker  * [Static types](#static-types)
14*57b5a4a6SAndroid Build Coastguard Worker  * [Designing serializable hierarchy](#designing-serializable-hierarchy)
15*57b5a4a6SAndroid Build Coastguard Worker  * [Sealed classes](#sealed-classes)
16*57b5a4a6SAndroid Build Coastguard Worker  * [Custom subclass serial name](#custom-subclass-serial-name)
17*57b5a4a6SAndroid Build Coastguard Worker  * [Concrete properties in a base class](#concrete-properties-in-a-base-class)
18*57b5a4a6SAndroid Build Coastguard Worker  * [Objects](#objects)
19*57b5a4a6SAndroid Build Coastguard Worker* [Open polymorphism](#open-polymorphism)
20*57b5a4a6SAndroid Build Coastguard Worker  * [Registered subclasses](#registered-subclasses)
21*57b5a4a6SAndroid Build Coastguard Worker  * [Serializing interfaces](#serializing-interfaces)
22*57b5a4a6SAndroid Build Coastguard Worker  * [Property of an interface type](#property-of-an-interface-type)
23*57b5a4a6SAndroid Build Coastguard Worker  * [Static parent type lookup for polymorphism](#static-parent-type-lookup-for-polymorphism)
24*57b5a4a6SAndroid Build Coastguard Worker  * [Explicitly marking polymorphic class properties](#explicitly-marking-polymorphic-class-properties)
25*57b5a4a6SAndroid Build Coastguard Worker  * [Registering multiple superclasses](#registering-multiple-superclasses)
26*57b5a4a6SAndroid Build Coastguard Worker  * [Polymorphism and generic classes](#polymorphism-and-generic-classes)
27*57b5a4a6SAndroid Build Coastguard Worker  * [Merging library serializers modules](#merging-library-serializers-modules)
28*57b5a4a6SAndroid Build Coastguard Worker  * [Default polymorphic type handler for deserialization](#default-polymorphic-type-handler-for-deserialization)
29*57b5a4a6SAndroid Build Coastguard Worker  * [Default polymorphic type handler for serialization](#default-polymorphic-type-handler-for-serialization)
30*57b5a4a6SAndroid Build Coastguard Worker
31*57b5a4a6SAndroid Build Coastguard Worker<!--- END -->
32*57b5a4a6SAndroid Build Coastguard Worker
33*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE .*-poly-.*
34*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.*
35*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.json.*
36*57b5a4a6SAndroid Build Coastguard Worker-->
37*57b5a4a6SAndroid Build Coastguard Worker
38*57b5a4a6SAndroid Build Coastguard Worker## Closed polymorphism
39*57b5a4a6SAndroid Build Coastguard Worker
40*57b5a4a6SAndroid Build Coastguard WorkerLet us start with basic introduction to polymorphism.
41*57b5a4a6SAndroid Build Coastguard Worker
42*57b5a4a6SAndroid Build Coastguard Worker### Static types
43*57b5a4a6SAndroid Build Coastguard Worker
44*57b5a4a6SAndroid Build Coastguard WorkerKotlin Serialization is fully static with respect to types by default. The structure of encoded objects is determined
45*57b5a4a6SAndroid Build Coastguard Workerby *compile-time* types of objects. Let's examine this aspect in more detail and learn how
46*57b5a4a6SAndroid Build Coastguard Workerto serialize polymorphic data structures, where the type of data is determined at runtime.
47*57b5a4a6SAndroid Build Coastguard Worker
48*57b5a4a6SAndroid Build Coastguard WorkerTo show the static nature of Kotlin Serialization let us make the following setup. An `open class Project`
49*57b5a4a6SAndroid Build Coastguard Workerhas just the `name` property, while its derived `class OwnedProject` adds an `owner` property.
50*57b5a4a6SAndroid Build Coastguard WorkerIn the below example, we serialize `data` variable with a static type of
51*57b5a4a6SAndroid Build Coastguard Worker`Project` that is initialized with an instance of `OwnedProject` at runtime.
52*57b5a4a6SAndroid Build Coastguard Worker
53*57b5a4a6SAndroid Build Coastguard Worker```kotlin
54*57b5a4a6SAndroid Build Coastguard Worker@Serializable
55*57b5a4a6SAndroid Build Coastguard Workeropen class Project(val name: String)
56*57b5a4a6SAndroid Build Coastguard Worker
57*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(name: String, val owner: String) : Project(name)
58*57b5a4a6SAndroid Build Coastguard Worker
59*57b5a4a6SAndroid Build Coastguard Workerfun main() {
60*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
61*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
62*57b5a4a6SAndroid Build Coastguard Worker}
63*57b5a4a6SAndroid Build Coastguard Worker```
64*57b5a4a6SAndroid Build Coastguard Worker
65*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-01.kt).
66*57b5a4a6SAndroid Build Coastguard Worker
67*57b5a4a6SAndroid Build Coastguard WorkerDespite the runtime type of `OwnedProject`, only the `Project` class properties are getting serialized.
68*57b5a4a6SAndroid Build Coastguard Worker
69*57b5a4a6SAndroid Build Coastguard Worker```text
70*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.coroutines"}
71*57b5a4a6SAndroid Build Coastguard Worker```
72*57b5a4a6SAndroid Build Coastguard Worker
73*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
74*57b5a4a6SAndroid Build Coastguard Worker
75*57b5a4a6SAndroid Build Coastguard WorkerLet's change the compile-time type of `data` to `OwnedProject`.
76*57b5a4a6SAndroid Build Coastguard Worker
77*57b5a4a6SAndroid Build Coastguard Worker```kotlin
78*57b5a4a6SAndroid Build Coastguard Worker@Serializable
79*57b5a4a6SAndroid Build Coastguard Workeropen class Project(val name: String)
80*57b5a4a6SAndroid Build Coastguard Worker
81*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(name: String, val owner: String) : Project(name)
82*57b5a4a6SAndroid Build Coastguard Worker
83*57b5a4a6SAndroid Build Coastguard Workerfun main() {
84*57b5a4a6SAndroid Build Coastguard Worker    val data = OwnedProject("kotlinx.coroutines", "kotlin")
85*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
86*57b5a4a6SAndroid Build Coastguard Worker}
87*57b5a4a6SAndroid Build Coastguard Worker```
88*57b5a4a6SAndroid Build Coastguard Worker
89*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-02.kt).
90*57b5a4a6SAndroid Build Coastguard Worker
91*57b5a4a6SAndroid Build Coastguard WorkerWe get an error, because the `OwnedProject` class is not serializable.
92*57b5a4a6SAndroid Build Coastguard Worker
93*57b5a4a6SAndroid Build Coastguard Worker```text
94*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.SerializationException: Serializer for class 'OwnedProject' is not found.
95*57b5a4a6SAndroid Build Coastguard WorkerPlease ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
96*57b5a4a6SAndroid Build Coastguard Worker```
97*57b5a4a6SAndroid Build Coastguard Worker
98*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
99*57b5a4a6SAndroid Build Coastguard Worker
100*57b5a4a6SAndroid Build Coastguard Worker### Designing serializable hierarchy
101*57b5a4a6SAndroid Build Coastguard Worker
102*57b5a4a6SAndroid Build Coastguard WorkerWe cannot simply mark `OwnedProject` from the previous example as `@Serializable`. It does not compile,
103*57b5a4a6SAndroid Build Coastguard Workerrunning into the [constructor properties requirement](basic-serialization.md#constructor-properties-requirement).
104*57b5a4a6SAndroid Build Coastguard WorkerTo make hierarchy of classes serializable, the properties in the parent class have to be marked `abstract`,
105*57b5a4a6SAndroid Build Coastguard Workermaking the `Project` class `abstract`, too.
106*57b5a4a6SAndroid Build Coastguard Worker
107*57b5a4a6SAndroid Build Coastguard Worker```kotlin
108*57b5a4a6SAndroid Build Coastguard Worker@Serializable
109*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
110*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
111*57b5a4a6SAndroid Build Coastguard Worker}
112*57b5a4a6SAndroid Build Coastguard Worker
113*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
114*57b5a4a6SAndroid Build Coastguard Worker
115*57b5a4a6SAndroid Build Coastguard Workerfun main() {
116*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
117*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
118*57b5a4a6SAndroid Build Coastguard Worker}
119*57b5a4a6SAndroid Build Coastguard Worker```
120*57b5a4a6SAndroid Build Coastguard Worker
121*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-03.kt).
122*57b5a4a6SAndroid Build Coastguard Worker
123*57b5a4a6SAndroid Build Coastguard WorkerThis is close to the best design for a serializable hierarchy of classes, but running it produces the following error:
124*57b5a4a6SAndroid Build Coastguard Worker
125*57b5a4a6SAndroid Build Coastguard Worker```text
126*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.SerializationException: Serializer for subclass 'OwnedProject' is not found in the polymorphic scope of 'Project'.
127*57b5a4a6SAndroid Build Coastguard WorkerCheck if class with serial name 'OwnedProject' exists and serializer is registered in a corresponding SerializersModule.
128*57b5a4a6SAndroid Build Coastguard WorkerTo be registered automatically, class 'OwnedProject' has to be '@Serializable', and the base class 'Project' has to be sealed and '@Serializable'.
129*57b5a4a6SAndroid Build Coastguard Worker```
130*57b5a4a6SAndroid Build Coastguard Worker
131*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
132*57b5a4a6SAndroid Build Coastguard Worker
133*57b5a4a6SAndroid Build Coastguard Worker### Sealed classes
134*57b5a4a6SAndroid Build Coastguard Worker
135*57b5a4a6SAndroid Build Coastguard WorkerThe most straightforward way to use serialization with a polymorphic hierarchy is to mark the base class `sealed`.
136*57b5a4a6SAndroid Build Coastguard Worker_All_ subclasses of a sealed class must be explicitly marked as `@Serializable`.
137*57b5a4a6SAndroid Build Coastguard Worker
138*57b5a4a6SAndroid Build Coastguard Worker```kotlin
139*57b5a4a6SAndroid Build Coastguard Worker@Serializable
140*57b5a4a6SAndroid Build Coastguard Workersealed class Project {
141*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
142*57b5a4a6SAndroid Build Coastguard Worker}
143*57b5a4a6SAndroid Build Coastguard Worker
144*57b5a4a6SAndroid Build Coastguard Worker@Serializable
145*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
146*57b5a4a6SAndroid Build Coastguard Worker
147*57b5a4a6SAndroid Build Coastguard Workerfun main() {
148*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
149*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data)) // Serializing data of compile-time type Project
150*57b5a4a6SAndroid Build Coastguard Worker}
151*57b5a4a6SAndroid Build Coastguard Worker```
152*57b5a4a6SAndroid Build Coastguard Worker
153*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-04.kt).
154*57b5a4a6SAndroid Build Coastguard Worker
155*57b5a4a6SAndroid Build Coastguard WorkerNow we can see a default way to represent polymorphism in JSON.
156*57b5a4a6SAndroid Build Coastguard WorkerA `type` key is added to the resulting JSON object as a _discriminator_.
157*57b5a4a6SAndroid Build Coastguard Worker
158*57b5a4a6SAndroid Build Coastguard Worker```text
159*57b5a4a6SAndroid Build Coastguard Worker{"type":"example.examplePoly04.OwnedProject","name":"kotlinx.coroutines","owner":"kotlin"}
160*57b5a4a6SAndroid Build Coastguard Worker```
161*57b5a4a6SAndroid Build Coastguard Worker
162*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
163*57b5a4a6SAndroid Build Coastguard Worker
164*57b5a4a6SAndroid Build Coastguard WorkerPay attention to the small, but very important detail in the above example that is related to [Static types](#static-types):
165*57b5a4a6SAndroid Build Coastguard Workerthe `val data` property has a compile-time type of `Project`, even though its run-time type is `OwnedProject`.
166*57b5a4a6SAndroid Build Coastguard WorkerWhen serializing polymorphic class hierarchies you must ensure that the compile-time type of the serialized object
167*57b5a4a6SAndroid Build Coastguard Workeris a polymorphic one, not a concrete one.
168*57b5a4a6SAndroid Build Coastguard Worker
169*57b5a4a6SAndroid Build Coastguard WorkerLet us see what happens if the example is slightly changed, so that the compile-time of the object that is being
170*57b5a4a6SAndroid Build Coastguard Workerserialized is `OwnedProject` (the same as its run-time type).
171*57b5a4a6SAndroid Build Coastguard Worker
172*57b5a4a6SAndroid Build Coastguard Worker```kotlin
173*57b5a4a6SAndroid Build Coastguard Worker@Serializable
174*57b5a4a6SAndroid Build Coastguard Workersealed class Project {
175*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
176*57b5a4a6SAndroid Build Coastguard Worker}
177*57b5a4a6SAndroid Build Coastguard Worker
178*57b5a4a6SAndroid Build Coastguard Worker@Serializable
179*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
180*57b5a4a6SAndroid Build Coastguard Worker
181*57b5a4a6SAndroid Build Coastguard Workerfun main() {
182*57b5a4a6SAndroid Build Coastguard Worker    val data = OwnedProject("kotlinx.coroutines", "kotlin") // data: OwnedProject here
183*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data)) // Serializing data of compile-time type OwnedProject
184*57b5a4a6SAndroid Build Coastguard Worker}
185*57b5a4a6SAndroid Build Coastguard Worker```
186*57b5a4a6SAndroid Build Coastguard Worker
187*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-05.kt).
188*57b5a4a6SAndroid Build Coastguard Worker
189*57b5a4a6SAndroid Build Coastguard WorkerThe type of `OwnedProject` is concrete and is not polymorphic, thus the `type`
190*57b5a4a6SAndroid Build Coastguard Workerdiscriminator property is not emitted into the resulting JSON.
191*57b5a4a6SAndroid Build Coastguard Worker
192*57b5a4a6SAndroid Build Coastguard Worker```text
193*57b5a4a6SAndroid Build Coastguard Worker{"name":"kotlinx.coroutines","owner":"kotlin"}
194*57b5a4a6SAndroid Build Coastguard Worker```
195*57b5a4a6SAndroid Build Coastguard Worker
196*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
197*57b5a4a6SAndroid Build Coastguard Worker
198*57b5a4a6SAndroid Build Coastguard WorkerIn general, Kotlin Serialization is designed to work correctly only when the compile-time type used during serialization
199*57b5a4a6SAndroid Build Coastguard Workeris the same one as the compile-time type used during deserialization. You can always specify the type explicitly
200*57b5a4a6SAndroid Build Coastguard Workerwhen calling serialization functions. The previous example can be corrected to use `Project` type for serialization
201*57b5a4a6SAndroid Build Coastguard Workerby calling `Json.encodeToString<Project>(data)`.
202*57b5a4a6SAndroid Build Coastguard Worker
203*57b5a4a6SAndroid Build Coastguard Worker### Custom subclass serial name
204*57b5a4a6SAndroid Build Coastguard Worker
205*57b5a4a6SAndroid Build Coastguard WorkerA value of the `type` key is a fully qualified class name by default. We can put [SerialName] annotation onto
206*57b5a4a6SAndroid Build Coastguard Workerthe corresponding class to change it.
207*57b5a4a6SAndroid Build Coastguard Worker
208*57b5a4a6SAndroid Build Coastguard Worker```kotlin
209*57b5a4a6SAndroid Build Coastguard Worker@Serializable
210*57b5a4a6SAndroid Build Coastguard Workersealed class Project {
211*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
212*57b5a4a6SAndroid Build Coastguard Worker}
213*57b5a4a6SAndroid Build Coastguard Worker
214*57b5a4a6SAndroid Build Coastguard Worker@Serializable
215*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
216*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
217*57b5a4a6SAndroid Build Coastguard Worker
218*57b5a4a6SAndroid Build Coastguard Workerfun main() {
219*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
220*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(data))
221*57b5a4a6SAndroid Build Coastguard Worker}
222*57b5a4a6SAndroid Build Coastguard Worker```
223*57b5a4a6SAndroid Build Coastguard Worker
224*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-06.kt).
225*57b5a4a6SAndroid Build Coastguard Worker
226*57b5a4a6SAndroid Build Coastguard WorkerThis way we can have a stable _serial name_ that is not affected by the class's name in the source code.
227*57b5a4a6SAndroid Build Coastguard Worker
228*57b5a4a6SAndroid Build Coastguard Worker```text
229*57b5a4a6SAndroid Build Coastguard Worker{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"}
230*57b5a4a6SAndroid Build Coastguard Worker```
231*57b5a4a6SAndroid Build Coastguard Worker
232*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
233*57b5a4a6SAndroid Build Coastguard Worker
234*57b5a4a6SAndroid Build Coastguard Worker> In addition to that, JSON can be configured to use a different key name for the class discriminator.
235*57b5a4a6SAndroid Build Coastguard Worker> You can find an example in the [Class discriminator for polymorphism](json.md#class-discriminator-for-polymorphism) section.
236*57b5a4a6SAndroid Build Coastguard Worker
237*57b5a4a6SAndroid Build Coastguard Worker### Concrete properties in a base class
238*57b5a4a6SAndroid Build Coastguard Worker
239*57b5a4a6SAndroid Build Coastguard WorkerA base class in a sealed hierarchy can have properties with backing fields.
240*57b5a4a6SAndroid Build Coastguard Worker
241*57b5a4a6SAndroid Build Coastguard Worker```kotlin
242*57b5a4a6SAndroid Build Coastguard Worker@Serializable
243*57b5a4a6SAndroid Build Coastguard Workersealed class Project {
244*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
245*57b5a4a6SAndroid Build Coastguard Worker    var status = "open"
246*57b5a4a6SAndroid Build Coastguard Worker}
247*57b5a4a6SAndroid Build Coastguard Worker
248*57b5a4a6SAndroid Build Coastguard Worker@Serializable
249*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
250*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
251*57b5a4a6SAndroid Build Coastguard Worker
252*57b5a4a6SAndroid Build Coastguard Workerfun main() {
253*57b5a4a6SAndroid Build Coastguard Worker    val json = Json { encodeDefaults = true } // "status" will be skipped otherwise
254*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
255*57b5a4a6SAndroid Build Coastguard Worker    println(json.encodeToString(data))
256*57b5a4a6SAndroid Build Coastguard Worker}
257*57b5a4a6SAndroid Build Coastguard Worker```
258*57b5a4a6SAndroid Build Coastguard Worker
259*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-07.kt).
260*57b5a4a6SAndroid Build Coastguard Worker
261*57b5a4a6SAndroid Build Coastguard WorkerThe properties of the superclass are serialized before the properties of the subclass.
262*57b5a4a6SAndroid Build Coastguard Worker
263*57b5a4a6SAndroid Build Coastguard Worker```text
264*57b5a4a6SAndroid Build Coastguard Worker{"type":"owned","status":"open","name":"kotlinx.coroutines","owner":"kotlin"}
265*57b5a4a6SAndroid Build Coastguard Worker```
266*57b5a4a6SAndroid Build Coastguard Worker
267*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
268*57b5a4a6SAndroid Build Coastguard Worker
269*57b5a4a6SAndroid Build Coastguard Worker### Objects
270*57b5a4a6SAndroid Build Coastguard Worker
271*57b5a4a6SAndroid Build Coastguard WorkerSealed hierarchies can have objects as their subclasses and they also need to be marked as `@Serializable`.
272*57b5a4a6SAndroid Build Coastguard WorkerLet's take a different example with a hierarchy of `Response` classes.
273*57b5a4a6SAndroid Build Coastguard Worker
274*57b5a4a6SAndroid Build Coastguard Worker```kotlin
275*57b5a4a6SAndroid Build Coastguard Worker@Serializable
276*57b5a4a6SAndroid Build Coastguard Workersealed class Response
277*57b5a4a6SAndroid Build Coastguard Worker
278*57b5a4a6SAndroid Build Coastguard Worker@Serializable
279*57b5a4a6SAndroid Build Coastguard Workerobject EmptyResponse : Response()
280*57b5a4a6SAndroid Build Coastguard Worker
281*57b5a4a6SAndroid Build Coastguard Worker@Serializable
282*57b5a4a6SAndroid Build Coastguard Workerclass TextResponse(val text: String) : Response()
283*57b5a4a6SAndroid Build Coastguard Worker```
284*57b5a4a6SAndroid Build Coastguard Worker
285*57b5a4a6SAndroid Build Coastguard WorkerLet us serialize a list of different responses.
286*57b5a4a6SAndroid Build Coastguard Worker
287*57b5a4a6SAndroid Build Coastguard Worker```kotlin
288*57b5a4a6SAndroid Build Coastguard Workerfun main() {
289*57b5a4a6SAndroid Build Coastguard Worker    val list = listOf(EmptyResponse, TextResponse("OK"))
290*57b5a4a6SAndroid Build Coastguard Worker    println(Json.encodeToString(list))
291*57b5a4a6SAndroid Build Coastguard Worker}
292*57b5a4a6SAndroid Build Coastguard Worker```
293*57b5a4a6SAndroid Build Coastguard Worker
294*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-08.kt).
295*57b5a4a6SAndroid Build Coastguard Worker
296*57b5a4a6SAndroid Build Coastguard WorkerAn object serializes as an empty class, also using its fully-qualified class name as type by default:
297*57b5a4a6SAndroid Build Coastguard Worker
298*57b5a4a6SAndroid Build Coastguard Worker```text
299*57b5a4a6SAndroid Build Coastguard Worker[{"type":"example.examplePoly08.EmptyResponse"},{"type":"example.examplePoly08.TextResponse","text":"OK"}]
300*57b5a4a6SAndroid Build Coastguard Worker```
301*57b5a4a6SAndroid Build Coastguard Worker
302*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
303*57b5a4a6SAndroid Build Coastguard Worker
304*57b5a4a6SAndroid Build Coastguard Worker> Even if object has properties, they are not serialized.
305*57b5a4a6SAndroid Build Coastguard Worker
306*57b5a4a6SAndroid Build Coastguard Worker## Open polymorphism
307*57b5a4a6SAndroid Build Coastguard Worker
308*57b5a4a6SAndroid Build Coastguard WorkerSerialization can work with arbitrary `open` classes or `abstract` classes.
309*57b5a4a6SAndroid Build Coastguard WorkerHowever, since this kind of polymorphism is open, there is a possibility that subclasses are defined anywhere in the
310*57b5a4a6SAndroid Build Coastguard Workersource code, even in other modules, the list of subclasses that are serialized cannot be determined at compile-time and
311*57b5a4a6SAndroid Build Coastguard Workermust be explicitly registered at runtime.
312*57b5a4a6SAndroid Build Coastguard Worker
313*57b5a4a6SAndroid Build Coastguard Worker### Registered subclasses
314*57b5a4a6SAndroid Build Coastguard Worker
315*57b5a4a6SAndroid Build Coastguard WorkerLet us start with the code from the [Designing serializable hierarchy](#designing-serializable-hierarchy) section.
316*57b5a4a6SAndroid Build Coastguard WorkerTo make it work with serialization without making it `sealed`, we have to define a [SerializersModule] using the
317*57b5a4a6SAndroid Build Coastguard Worker[SerializersModule {}][SerializersModule()] builder function. In the module the base class is specified
318*57b5a4a6SAndroid Build Coastguard Workerin the [polymorphic][_polymorphic] builder and each subclass is registered with the [subclass] function. Now,
319*57b5a4a6SAndroid Build Coastguard Workera custom JSON configuration can be instantiated with this module and used for serialization.
320*57b5a4a6SAndroid Build Coastguard Worker
321*57b5a4a6SAndroid Build Coastguard Worker> Details on custom JSON configurations can be found in
322*57b5a4a6SAndroid Build Coastguard Worker> the [JSON configuration](json.md#json-configuration) section.
323*57b5a4a6SAndroid Build Coastguard Worker
324*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
325*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
326*57b5a4a6SAndroid Build Coastguard Worker-->
327*57b5a4a6SAndroid Build Coastguard Worker
328*57b5a4a6SAndroid Build Coastguard Worker```kotlin
329*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
330*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) {
331*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
332*57b5a4a6SAndroid Build Coastguard Worker    }
333*57b5a4a6SAndroid Build Coastguard Worker}
334*57b5a4a6SAndroid Build Coastguard Worker
335*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
336*57b5a4a6SAndroid Build Coastguard Worker
337*57b5a4a6SAndroid Build Coastguard Worker@Serializable
338*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
339*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
340*57b5a4a6SAndroid Build Coastguard Worker}
341*57b5a4a6SAndroid Build Coastguard Worker
342*57b5a4a6SAndroid Build Coastguard Worker@Serializable
343*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
344*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
345*57b5a4a6SAndroid Build Coastguard Worker
346*57b5a4a6SAndroid Build Coastguard Workerfun main() {
347*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
348*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
349*57b5a4a6SAndroid Build Coastguard Worker}
350*57b5a4a6SAndroid Build Coastguard Worker```
351*57b5a4a6SAndroid Build Coastguard Worker
352*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-09.kt).
353*57b5a4a6SAndroid Build Coastguard Worker
354*57b5a4a6SAndroid Build Coastguard WorkerThis additional configuration makes our code work just as it worked with a sealed class in
355*57b5a4a6SAndroid Build Coastguard Workerthe [Sealed classes](#sealed-classes) section, but here subclasses can be spread arbitrarily throughout the code.
356*57b5a4a6SAndroid Build Coastguard Worker
357*57b5a4a6SAndroid Build Coastguard Worker```text
358*57b5a4a6SAndroid Build Coastguard Worker{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"}
359*57b5a4a6SAndroid Build Coastguard Worker```
360*57b5a4a6SAndroid Build Coastguard Worker
361*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
362*57b5a4a6SAndroid Build Coastguard Worker>Please note that this example works only on JVM because of `serializer` function restrictions.
363*57b5a4a6SAndroid Build Coastguard Worker>For JS and Native, explicit serializer should be used: `format.encodeToString(PolymorphicSerializer(Project::class), data)`
364*57b5a4a6SAndroid Build Coastguard Worker>You can keep track of this issue [here](https://github.com/Kotlin/kotlinx.serialization/issues/1077).
365*57b5a4a6SAndroid Build Coastguard Worker
366*57b5a4a6SAndroid Build Coastguard Worker### Serializing interfaces
367*57b5a4a6SAndroid Build Coastguard Worker
368*57b5a4a6SAndroid Build Coastguard WorkerWe can update the previous example and turn `Project` superclass into an interface. However, we cannot
369*57b5a4a6SAndroid Build Coastguard Workermark an interface itself as `@Serializable`. No problem. Interfaces cannot have instances by themselves.
370*57b5a4a6SAndroid Build Coastguard WorkerInterfaces can only be represented by instances of their derived classes. Interfaces are used in the Kotlin language to enable polymorphism,
371*57b5a4a6SAndroid Build Coastguard Workerso all interfaces are considered to be implicitly serializable with the [PolymorphicSerializer]
372*57b5a4a6SAndroid Build Coastguard Workerstrategy. We just need to mark their implementing classes as `@Serializable` and register them.
373*57b5a4a6SAndroid Build Coastguard Worker
374*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
375*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
376*57b5a4a6SAndroid Build Coastguard Worker
377*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
378*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) {
379*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
380*57b5a4a6SAndroid Build Coastguard Worker    }
381*57b5a4a6SAndroid Build Coastguard Worker}
382*57b5a4a6SAndroid Build Coastguard Worker
383*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
384*57b5a4a6SAndroid Build Coastguard Worker-->
385*57b5a4a6SAndroid Build Coastguard Worker
386*57b5a4a6SAndroid Build Coastguard Worker```kotlin
387*57b5a4a6SAndroid Build Coastguard Workerinterface Project {
388*57b5a4a6SAndroid Build Coastguard Worker    val name: String
389*57b5a4a6SAndroid Build Coastguard Worker}
390*57b5a4a6SAndroid Build Coastguard Worker
391*57b5a4a6SAndroid Build Coastguard Worker@Serializable
392*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
393*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project
394*57b5a4a6SAndroid Build Coastguard Worker```
395*57b5a4a6SAndroid Build Coastguard Worker
396*57b5a4a6SAndroid Build Coastguard WorkerNow if we declare `data` with the type of `Project` we can simply call `format.encodeToString` as before.
397*57b5a4a6SAndroid Build Coastguard Worker
398*57b5a4a6SAndroid Build Coastguard Worker```kotlin
399*57b5a4a6SAndroid Build Coastguard Workerfun main() {
400*57b5a4a6SAndroid Build Coastguard Worker    val data: Project = OwnedProject("kotlinx.coroutines", "kotlin")
401*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
402*57b5a4a6SAndroid Build Coastguard Worker}
403*57b5a4a6SAndroid Build Coastguard Worker```
404*57b5a4a6SAndroid Build Coastguard Worker
405*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-10.kt).
406*57b5a4a6SAndroid Build Coastguard Worker
407*57b5a4a6SAndroid Build Coastguard Worker```text
408*57b5a4a6SAndroid Build Coastguard Worker{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"}
409*57b5a4a6SAndroid Build Coastguard Worker```
410*57b5a4a6SAndroid Build Coastguard Worker
411*57b5a4a6SAndroid Build Coastguard Worker> Note: On Kotlin/Native, you should use `format.encodeToString(PolymorphicSerializer(Project::class), data))` instead due to limited reflection capabilities.
412*57b5a4a6SAndroid Build Coastguard Worker
413*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
414*57b5a4a6SAndroid Build Coastguard Worker
415*57b5a4a6SAndroid Build Coastguard Worker### Property of an interface type
416*57b5a4a6SAndroid Build Coastguard Worker
417*57b5a4a6SAndroid Build Coastguard WorkerContinuing the previous example, let us see what happens if we use `Project` interface as a property in some
418*57b5a4a6SAndroid Build Coastguard Workerother serializable class. Interfaces are implicitly polymorphic, so we can just declare a property of an interface type.
419*57b5a4a6SAndroid Build Coastguard Worker
420*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
421*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
422*57b5a4a6SAndroid Build Coastguard Worker
423*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
424*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) {
425*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
426*57b5a4a6SAndroid Build Coastguard Worker    }
427*57b5a4a6SAndroid Build Coastguard Worker}
428*57b5a4a6SAndroid Build Coastguard Worker
429*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
430*57b5a4a6SAndroid Build Coastguard Worker
431*57b5a4a6SAndroid Build Coastguard Workerinterface Project {
432*57b5a4a6SAndroid Build Coastguard Worker    val name: String
433*57b5a4a6SAndroid Build Coastguard Worker}
434*57b5a4a6SAndroid Build Coastguard Worker
435*57b5a4a6SAndroid Build Coastguard Worker@Serializable
436*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
437*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project
438*57b5a4a6SAndroid Build Coastguard Worker-->
439*57b5a4a6SAndroid Build Coastguard Worker
440*57b5a4a6SAndroid Build Coastguard Worker```kotlin
441*57b5a4a6SAndroid Build Coastguard Worker@Serializable
442*57b5a4a6SAndroid Build Coastguard Workerclass Data(val project: Project) // Project is an interface
443*57b5a4a6SAndroid Build Coastguard Worker
444*57b5a4a6SAndroid Build Coastguard Workerfun main() {
445*57b5a4a6SAndroid Build Coastguard Worker    val data = Data(OwnedProject("kotlinx.coroutines", "kotlin"))
446*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
447*57b5a4a6SAndroid Build Coastguard Worker}
448*57b5a4a6SAndroid Build Coastguard Worker```
449*57b5a4a6SAndroid Build Coastguard Worker
450*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-11.kt).
451*57b5a4a6SAndroid Build Coastguard Worker
452*57b5a4a6SAndroid Build Coastguard WorkerAs long as we've registered the actual subtype of the interface that is being serialized in
453*57b5a4a6SAndroid Build Coastguard Workerthe [SerializersModule] of our `format`, we get it working at runtime.
454*57b5a4a6SAndroid Build Coastguard Worker
455*57b5a4a6SAndroid Build Coastguard Worker```text
456*57b5a4a6SAndroid Build Coastguard Worker{"project":{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"}}
457*57b5a4a6SAndroid Build Coastguard Worker```
458*57b5a4a6SAndroid Build Coastguard Worker
459*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
460*57b5a4a6SAndroid Build Coastguard Worker
461*57b5a4a6SAndroid Build Coastguard Worker### Static parent type lookup for polymorphism
462*57b5a4a6SAndroid Build Coastguard Worker
463*57b5a4a6SAndroid Build Coastguard WorkerDuring serialization of a polymorphic class the root type of the polymorphic hierarchy (`Project` in our example)
464*57b5a4a6SAndroid Build Coastguard Workeris determined statically. Let us take the example with the serializable `abstract class Project`,
465*57b5a4a6SAndroid Build Coastguard Workerbut change the `main` function to declare `data` as having a type of `Any`:
466*57b5a4a6SAndroid Build Coastguard Worker
467*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
468*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
469*57b5a4a6SAndroid Build Coastguard Worker
470*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
471*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) {
472*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
473*57b5a4a6SAndroid Build Coastguard Worker    }
474*57b5a4a6SAndroid Build Coastguard Worker}
475*57b5a4a6SAndroid Build Coastguard Worker
476*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
477*57b5a4a6SAndroid Build Coastguard Worker
478*57b5a4a6SAndroid Build Coastguard Worker@Serializable
479*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
480*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
481*57b5a4a6SAndroid Build Coastguard Worker}
482*57b5a4a6SAndroid Build Coastguard Worker
483*57b5a4a6SAndroid Build Coastguard Worker@Serializable
484*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
485*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
486*57b5a4a6SAndroid Build Coastguard Worker-->
487*57b5a4a6SAndroid Build Coastguard Worker
488*57b5a4a6SAndroid Build Coastguard Worker```kotlin
489*57b5a4a6SAndroid Build Coastguard Workerfun main() {
490*57b5a4a6SAndroid Build Coastguard Worker    val data: Any = OwnedProject("kotlinx.coroutines", "kotlin")
491*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
492*57b5a4a6SAndroid Build Coastguard Worker}
493*57b5a4a6SAndroid Build Coastguard Worker```
494*57b5a4a6SAndroid Build Coastguard Worker
495*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-12.kt).
496*57b5a4a6SAndroid Build Coastguard Worker
497*57b5a4a6SAndroid Build Coastguard WorkerWe get the exception.
498*57b5a4a6SAndroid Build Coastguard Worker
499*57b5a4a6SAndroid Build Coastguard Worker```text
500*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.SerializationException: Serializer for class 'Any' is not found.
501*57b5a4a6SAndroid Build Coastguard WorkerPlease ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
502*57b5a4a6SAndroid Build Coastguard Worker```
503*57b5a4a6SAndroid Build Coastguard Worker
504*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
505*57b5a4a6SAndroid Build Coastguard Worker
506*57b5a4a6SAndroid Build Coastguard WorkerWe have to register classes for polymorphic serialization with respect for the corresponding static type we
507*57b5a4a6SAndroid Build Coastguard Workeruse in the source code. First of all, we change our module to register a subclass of `Any`:
508*57b5a4a6SAndroid Build Coastguard Worker
509*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
510*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
511*57b5a4a6SAndroid Build Coastguard Worker-->
512*57b5a4a6SAndroid Build Coastguard Worker
513*57b5a4a6SAndroid Build Coastguard Worker```kotlin
514*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
515*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Any::class) {
516*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
517*57b5a4a6SAndroid Build Coastguard Worker    }
518*57b5a4a6SAndroid Build Coastguard Worker}
519*57b5a4a6SAndroid Build Coastguard Worker```
520*57b5a4a6SAndroid Build Coastguard Worker
521*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
522*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
523*57b5a4a6SAndroid Build Coastguard Worker
524*57b5a4a6SAndroid Build Coastguard Worker@Serializable
525*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
526*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
527*57b5a4a6SAndroid Build Coastguard Worker}
528*57b5a4a6SAndroid Build Coastguard Worker
529*57b5a4a6SAndroid Build Coastguard Worker@Serializable
530*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
531*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
532*57b5a4a6SAndroid Build Coastguard Worker-->
533*57b5a4a6SAndroid Build Coastguard Worker
534*57b5a4a6SAndroid Build Coastguard WorkerThen we can try to serialize the variable of type `Any`:
535*57b5a4a6SAndroid Build Coastguard Worker
536*57b5a4a6SAndroid Build Coastguard Worker```kotlin
537*57b5a4a6SAndroid Build Coastguard Workerfun main() {
538*57b5a4a6SAndroid Build Coastguard Worker    val data: Any = OwnedProject("kotlinx.coroutines", "kotlin")
539*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
540*57b5a4a6SAndroid Build Coastguard Worker}
541*57b5a4a6SAndroid Build Coastguard Worker```
542*57b5a4a6SAndroid Build Coastguard Worker
543*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-13.kt).
544*57b5a4a6SAndroid Build Coastguard Worker
545*57b5a4a6SAndroid Build Coastguard WorkerHowever, `Any` is a class and it is not serializable:
546*57b5a4a6SAndroid Build Coastguard Worker
547*57b5a4a6SAndroid Build Coastguard Worker```text
548*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.SerializationException: Serializer for class 'Any' is not found.
549*57b5a4a6SAndroid Build Coastguard WorkerPlease ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
550*57b5a4a6SAndroid Build Coastguard Worker```
551*57b5a4a6SAndroid Build Coastguard Worker
552*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
553*57b5a4a6SAndroid Build Coastguard Worker
554*57b5a4a6SAndroid Build Coastguard WorkerWe must to explicitly pass an instance of [PolymorphicSerializer] for the base class `Any` as the
555*57b5a4a6SAndroid Build Coastguard Workerfirst parameter to the [encodeToString][Json.encodeToString] function.
556*57b5a4a6SAndroid Build Coastguard Worker
557*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
558*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
559*57b5a4a6SAndroid Build Coastguard Worker
560*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
561*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Any::class) {
562*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
563*57b5a4a6SAndroid Build Coastguard Worker    }
564*57b5a4a6SAndroid Build Coastguard Worker}
565*57b5a4a6SAndroid Build Coastguard Worker
566*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
567*57b5a4a6SAndroid Build Coastguard Worker
568*57b5a4a6SAndroid Build Coastguard Worker@Serializable
569*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
570*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
571*57b5a4a6SAndroid Build Coastguard Worker}
572*57b5a4a6SAndroid Build Coastguard Worker
573*57b5a4a6SAndroid Build Coastguard Worker@Serializable
574*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
575*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project()
576*57b5a4a6SAndroid Build Coastguard Worker-->
577*57b5a4a6SAndroid Build Coastguard Worker
578*57b5a4a6SAndroid Build Coastguard Worker```kotlin
579*57b5a4a6SAndroid Build Coastguard Workerfun main() {
580*57b5a4a6SAndroid Build Coastguard Worker    val data: Any = OwnedProject("kotlinx.coroutines", "kotlin")
581*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(PolymorphicSerializer(Any::class), data))
582*57b5a4a6SAndroid Build Coastguard Worker}
583*57b5a4a6SAndroid Build Coastguard Worker```
584*57b5a4a6SAndroid Build Coastguard Worker
585*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-14.kt).
586*57b5a4a6SAndroid Build Coastguard Worker
587*57b5a4a6SAndroid Build Coastguard WorkerWith the explicit serializer it works as before.
588*57b5a4a6SAndroid Build Coastguard Worker
589*57b5a4a6SAndroid Build Coastguard Worker```text
590*57b5a4a6SAndroid Build Coastguard Worker{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"}
591*57b5a4a6SAndroid Build Coastguard Worker```
592*57b5a4a6SAndroid Build Coastguard Worker
593*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
594*57b5a4a6SAndroid Build Coastguard Worker
595*57b5a4a6SAndroid Build Coastguard Worker### Explicitly marking polymorphic class properties
596*57b5a4a6SAndroid Build Coastguard Worker
597*57b5a4a6SAndroid Build Coastguard WorkerThe property of an interface type is implicitly considered polymorphic, since interfaces are all about runtime polymorphism.
598*57b5a4a6SAndroid Build Coastguard WorkerHowever, Kotlin Serialization does not compile a serializable class with a property of a non-serializable class type.
599*57b5a4a6SAndroid Build Coastguard WorkerIf we have a property of `Any` class or other non-serializable class, then we must explicitly provide its serialization
600*57b5a4a6SAndroid Build Coastguard Workerstrategy via the [`@Serializable`][Serializable] annotation as we saw in
601*57b5a4a6SAndroid Build Coastguard Workerthe [Specifying serializer on a property](serializers.md#specifying-serializer-on-a-property) section.
602*57b5a4a6SAndroid Build Coastguard WorkerTo specify a polymorphic serialization strategy of a property, the special-purpose [`@Polymorphic`][Polymorphic]
603*57b5a4a6SAndroid Build Coastguard Workerannotation is used.
604*57b5a4a6SAndroid Build Coastguard Worker
605*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
606*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
607*57b5a4a6SAndroid Build Coastguard Worker
608*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
609*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Any::class) {
610*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
611*57b5a4a6SAndroid Build Coastguard Worker    }
612*57b5a4a6SAndroid Build Coastguard Worker}
613*57b5a4a6SAndroid Build Coastguard Worker
614*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
615*57b5a4a6SAndroid Build Coastguard Worker
616*57b5a4a6SAndroid Build Coastguard Workerinterface Project {
617*57b5a4a6SAndroid Build Coastguard Worker    val name: String
618*57b5a4a6SAndroid Build Coastguard Worker}
619*57b5a4a6SAndroid Build Coastguard Worker
620*57b5a4a6SAndroid Build Coastguard Worker@Serializable
621*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
622*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project
623*57b5a4a6SAndroid Build Coastguard Worker-->
624*57b5a4a6SAndroid Build Coastguard Worker
625*57b5a4a6SAndroid Build Coastguard Worker```kotlin
626*57b5a4a6SAndroid Build Coastguard Worker@Serializable
627*57b5a4a6SAndroid Build Coastguard Workerclass Data(
628*57b5a4a6SAndroid Build Coastguard Worker    @Polymorphic // the code does not compile without it
629*57b5a4a6SAndroid Build Coastguard Worker    val project: Any
630*57b5a4a6SAndroid Build Coastguard Worker)
631*57b5a4a6SAndroid Build Coastguard Worker
632*57b5a4a6SAndroid Build Coastguard Workerfun main() {
633*57b5a4a6SAndroid Build Coastguard Worker    val data = Data(OwnedProject("kotlinx.coroutines", "kotlin"))
634*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
635*57b5a4a6SAndroid Build Coastguard Worker}
636*57b5a4a6SAndroid Build Coastguard Worker```
637*57b5a4a6SAndroid Build Coastguard Worker
638*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-15.kt).
639*57b5a4a6SAndroid Build Coastguard Worker
640*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST
641*57b5a4a6SAndroid Build Coastguard Worker{"project":{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"}}
642*57b5a4a6SAndroid Build Coastguard Worker-->
643*57b5a4a6SAndroid Build Coastguard Worker
644*57b5a4a6SAndroid Build Coastguard Worker### Registering multiple superclasses
645*57b5a4a6SAndroid Build Coastguard Worker
646*57b5a4a6SAndroid Build Coastguard WorkerWhen the same class gets serialized as a value of properties with different compile-time type from the list of
647*57b5a4a6SAndroid Build Coastguard Workerits superclasses, we must register it in the [SerializersModule] for each of its superclasses separately.
648*57b5a4a6SAndroid Build Coastguard WorkerIt is convenient to extract registration of all the subclasses into a separate function and
649*57b5a4a6SAndroid Build Coastguard Workeruse it for each superclass. You can use the following template to write it.
650*57b5a4a6SAndroid Build Coastguard Worker
651*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
652*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
653*57b5a4a6SAndroid Build Coastguard Workerimport kotlin.reflect.KClass
654*57b5a4a6SAndroid Build Coastguard Worker-->
655*57b5a4a6SAndroid Build Coastguard Worker
656*57b5a4a6SAndroid Build Coastguard Worker```kotlin
657*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
658*57b5a4a6SAndroid Build Coastguard Worker    fun PolymorphicModuleBuilder<Project>.registerProjectSubclasses() {
659*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
660*57b5a4a6SAndroid Build Coastguard Worker    }
661*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Any::class) { registerProjectSubclasses() }
662*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) { registerProjectSubclasses() }
663*57b5a4a6SAndroid Build Coastguard Worker}
664*57b5a4a6SAndroid Build Coastguard Worker```
665*57b5a4a6SAndroid Build Coastguard Worker
666*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
667*57b5a4a6SAndroid Build Coastguard Worker
668*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
669*57b5a4a6SAndroid Build Coastguard Worker
670*57b5a4a6SAndroid Build Coastguard Workerinterface Project {
671*57b5a4a6SAndroid Build Coastguard Worker    val name: String
672*57b5a4a6SAndroid Build Coastguard Worker}
673*57b5a4a6SAndroid Build Coastguard Worker
674*57b5a4a6SAndroid Build Coastguard Worker@Serializable
675*57b5a4a6SAndroid Build Coastguard Worker@SerialName("owned")
676*57b5a4a6SAndroid Build Coastguard Workerclass OwnedProject(override val name: String, val owner: String) : Project
677*57b5a4a6SAndroid Build Coastguard Worker
678*57b5a4a6SAndroid Build Coastguard Worker@Serializable
679*57b5a4a6SAndroid Build Coastguard Workerclass Data(
680*57b5a4a6SAndroid Build Coastguard Worker    val project: Project,
681*57b5a4a6SAndroid Build Coastguard Worker    @Polymorphic val any: Any
682*57b5a4a6SAndroid Build Coastguard Worker)
683*57b5a4a6SAndroid Build Coastguard Worker
684*57b5a4a6SAndroid Build Coastguard Workerfun main() {
685*57b5a4a6SAndroid Build Coastguard Worker    val project = OwnedProject("kotlinx.coroutines", "kotlin")
686*57b5a4a6SAndroid Build Coastguard Worker    val data = Data(project, project)
687*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString(data))
688*57b5a4a6SAndroid Build Coastguard Worker}
689*57b5a4a6SAndroid Build Coastguard Worker-->
690*57b5a4a6SAndroid Build Coastguard Worker
691*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-16.kt).
692*57b5a4a6SAndroid Build Coastguard Worker
693*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST
694*57b5a4a6SAndroid Build Coastguard Worker{"project":{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"},"any":{"type":"owned","name":"kotlinx.coroutines","owner":"kotlin"}}
695*57b5a4a6SAndroid Build Coastguard Worker-->
696*57b5a4a6SAndroid Build Coastguard Worker
697*57b5a4a6SAndroid Build Coastguard Worker### Polymorphism and generic classes
698*57b5a4a6SAndroid Build Coastguard Worker
699*57b5a4a6SAndroid Build Coastguard WorkerGeneric subtypes for a serializable class require a special handling. Consider the following hierarchy.
700*57b5a4a6SAndroid Build Coastguard Worker
701*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
702*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
703*57b5a4a6SAndroid Build Coastguard Worker-->
704*57b5a4a6SAndroid Build Coastguard Worker
705*57b5a4a6SAndroid Build Coastguard Worker```kotlin
706*57b5a4a6SAndroid Build Coastguard Worker@Serializable
707*57b5a4a6SAndroid Build Coastguard Workerabstract class Response<out T>
708*57b5a4a6SAndroid Build Coastguard Worker
709*57b5a4a6SAndroid Build Coastguard Worker@Serializable
710*57b5a4a6SAndroid Build Coastguard Worker@SerialName("OkResponse")
711*57b5a4a6SAndroid Build Coastguard Workerdata class OkResponse<out T>(val data: T) : Response<T>()
712*57b5a4a6SAndroid Build Coastguard Worker```
713*57b5a4a6SAndroid Build Coastguard Worker
714*57b5a4a6SAndroid Build Coastguard WorkerKotlin Serialization does not have a builtin strategy to represent the actually provided argument type for the
715*57b5a4a6SAndroid Build Coastguard Workertype parameter `T` when serializing a property of the polymorphic type `OkResponse<T>`. We have to provide this
716*57b5a4a6SAndroid Build Coastguard Workerstrategy explicitly when defining the serializers module for the `Response`. In the below example we
717*57b5a4a6SAndroid Build Coastguard Workeruse `OkResponse.serializer(...)` to retrieve
718*57b5a4a6SAndroid Build Coastguard Workerthe [Plugin-generated generic serializer](serializers.md#plugin-generated-generic-serializer) of
719*57b5a4a6SAndroid Build Coastguard Workerthe `OkResponse` class and instantiate it with the [PolymorphicSerializer] instance with
720*57b5a4a6SAndroid Build Coastguard Worker`Any` class as its base. This way, we can serialize an instance of `OkResponse` with any `data` property that
721*57b5a4a6SAndroid Build Coastguard Workerwas polymorphically registered as a subtype of `Any`.
722*57b5a4a6SAndroid Build Coastguard Worker
723*57b5a4a6SAndroid Build Coastguard Worker```kotlin
724*57b5a4a6SAndroid Build Coastguard Workerval responseModule = SerializersModule {
725*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Response::class) {
726*57b5a4a6SAndroid Build Coastguard Worker        subclass(OkResponse.serializer(PolymorphicSerializer(Any::class)))
727*57b5a4a6SAndroid Build Coastguard Worker    }
728*57b5a4a6SAndroid Build Coastguard Worker}
729*57b5a4a6SAndroid Build Coastguard Worker```
730*57b5a4a6SAndroid Build Coastguard Worker
731*57b5a4a6SAndroid Build Coastguard Worker### Merging library serializers modules
732*57b5a4a6SAndroid Build Coastguard Worker
733*57b5a4a6SAndroid Build Coastguard WorkerWhen the application grows in size and splits into source code modules,
734*57b5a4a6SAndroid Build Coastguard Workerit may become inconvenient to store all class hierarchies in one serializers module.
735*57b5a4a6SAndroid Build Coastguard WorkerLet us add a library with the `Project` hierarchy to the code from the previous section.
736*57b5a4a6SAndroid Build Coastguard Worker
737*57b5a4a6SAndroid Build Coastguard Worker```kotlin
738*57b5a4a6SAndroid Build Coastguard Workerval projectModule = SerializersModule {
739*57b5a4a6SAndroid Build Coastguard Worker    fun PolymorphicModuleBuilder<Project>.registerProjectSubclasses() {
740*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
741*57b5a4a6SAndroid Build Coastguard Worker    }
742*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Any::class) { registerProjectSubclasses() }
743*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) { registerProjectSubclasses() }
744*57b5a4a6SAndroid Build Coastguard Worker}
745*57b5a4a6SAndroid Build Coastguard Worker```
746*57b5a4a6SAndroid Build Coastguard Worker
747*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
748*57b5a4a6SAndroid Build Coastguard Worker
749*57b5a4a6SAndroid Build Coastguard Worker@Serializable
750*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
751*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
752*57b5a4a6SAndroid Build Coastguard Worker}
753*57b5a4a6SAndroid Build Coastguard Worker
754*57b5a4a6SAndroid Build Coastguard Worker@Serializable
755*57b5a4a6SAndroid Build Coastguard Worker@SerialName("OwnedProject")
756*57b5a4a6SAndroid Build Coastguard Workerdata class OwnedProject(override val name: String, val owner: String) : Project()
757*57b5a4a6SAndroid Build Coastguard Worker-->
758*57b5a4a6SAndroid Build Coastguard Worker
759*57b5a4a6SAndroid Build Coastguard WorkerWe can compose those two modules together using the  [plus] operator to merge them,
760*57b5a4a6SAndroid Build Coastguard Workerso that we can use them both in the same [Json] format instance.
761*57b5a4a6SAndroid Build Coastguard Worker
762*57b5a4a6SAndroid Build Coastguard Worker> You can also use the [include][SerializersModuleBuilder.include] function
763*57b5a4a6SAndroid Build Coastguard Worker> in the [SerializersModule {}][SerializersModule()] DSL.
764*57b5a4a6SAndroid Build Coastguard Worker
765*57b5a4a6SAndroid Build Coastguard Worker```kotlin
766*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = projectModule + responseModule }
767*57b5a4a6SAndroid Build Coastguard Worker````
768*57b5a4a6SAndroid Build Coastguard Worker
769*57b5a4a6SAndroid Build Coastguard WorkerNow classes from both hierarchies can be serialized together and deserialized together.
770*57b5a4a6SAndroid Build Coastguard Worker
771*57b5a4a6SAndroid Build Coastguard Worker```kotlin
772*57b5a4a6SAndroid Build Coastguard Workerfun main() {
773*57b5a4a6SAndroid Build Coastguard Worker    // both Response and Project are abstract and their concrete subtypes are being serialized
774*57b5a4a6SAndroid Build Coastguard Worker    val data: Response<Project> =  OkResponse(OwnedProject("kotlinx.serialization", "kotlin"))
775*57b5a4a6SAndroid Build Coastguard Worker    val string = format.encodeToString(data)
776*57b5a4a6SAndroid Build Coastguard Worker    println(string)
777*57b5a4a6SAndroid Build Coastguard Worker    println(format.decodeFromString<Response<Project>>(string))
778*57b5a4a6SAndroid Build Coastguard Worker}
779*57b5a4a6SAndroid Build Coastguard Worker
780*57b5a4a6SAndroid Build Coastguard Worker```
781*57b5a4a6SAndroid Build Coastguard Worker
782*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-17.kt).
783*57b5a4a6SAndroid Build Coastguard Worker
784*57b5a4a6SAndroid Build Coastguard WorkerThe JSON that is being produced is deeply polymorphic.
785*57b5a4a6SAndroid Build Coastguard Worker
786*57b5a4a6SAndroid Build Coastguard Worker```text
787*57b5a4a6SAndroid Build Coastguard Worker{"type":"OkResponse","data":{"type":"OwnedProject","name":"kotlinx.serialization","owner":"kotlin"}}
788*57b5a4a6SAndroid Build Coastguard WorkerOkResponse(data=OwnedProject(name=kotlinx.serialization, owner=kotlin))
789*57b5a4a6SAndroid Build Coastguard Worker```
790*57b5a4a6SAndroid Build Coastguard Worker
791*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
792*57b5a4a6SAndroid Build Coastguard Worker
793*57b5a4a6SAndroid Build Coastguard WorkerIf you're writing a library or shared module with an abstract class and some implementations of it,
794*57b5a4a6SAndroid Build Coastguard Workeryou can expose your own serializers module for your clients to use so that a client can combine your
795*57b5a4a6SAndroid Build Coastguard Workermodule with their modules.
796*57b5a4a6SAndroid Build Coastguard Worker
797*57b5a4a6SAndroid Build Coastguard Worker### Default polymorphic type handler for deserialization
798*57b5a4a6SAndroid Build Coastguard Worker
799*57b5a4a6SAndroid Build Coastguard WorkerWhat happens when we deserialize a subclass that was not registered?
800*57b5a4a6SAndroid Build Coastguard Worker
801*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
802*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
803*57b5a4a6SAndroid Build Coastguard Worker
804*57b5a4a6SAndroid Build Coastguard Worker@Serializable
805*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
806*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
807*57b5a4a6SAndroid Build Coastguard Worker}
808*57b5a4a6SAndroid Build Coastguard Worker
809*57b5a4a6SAndroid Build Coastguard Worker@Serializable
810*57b5a4a6SAndroid Build Coastguard Worker@SerialName("OwnedProject")
811*57b5a4a6SAndroid Build Coastguard Workerdata class OwnedProject(override val name: String, val owner: String) : Project()
812*57b5a4a6SAndroid Build Coastguard Worker
813*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
814*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) {
815*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
816*57b5a4a6SAndroid Build Coastguard Worker    }
817*57b5a4a6SAndroid Build Coastguard Worker}
818*57b5a4a6SAndroid Build Coastguard Worker
819*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
820*57b5a4a6SAndroid Build Coastguard Worker-->
821*57b5a4a6SAndroid Build Coastguard Worker
822*57b5a4a6SAndroid Build Coastguard Worker```kotlin
823*57b5a4a6SAndroid Build Coastguard Workerfun main() {
824*57b5a4a6SAndroid Build Coastguard Worker    println(format.decodeFromString<Project>("""
825*57b5a4a6SAndroid Build Coastguard Worker        {"type":"unknown","name":"example"}
826*57b5a4a6SAndroid Build Coastguard Worker    """))
827*57b5a4a6SAndroid Build Coastguard Worker}
828*57b5a4a6SAndroid Build Coastguard Worker```
829*57b5a4a6SAndroid Build Coastguard Worker
830*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-18.kt).
831*57b5a4a6SAndroid Build Coastguard Worker
832*57b5a4a6SAndroid Build Coastguard WorkerWe get the following exception.
833*57b5a4a6SAndroid Build Coastguard Worker
834*57b5a4a6SAndroid Build Coastguard Worker```text
835*57b5a4a6SAndroid Build Coastguard WorkerException in thread "main" kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 0: Serializer for subclass 'unknown' is not found in the polymorphic scope of 'Project' at path: $
836*57b5a4a6SAndroid Build Coastguard WorkerCheck if class with serial name 'unknown' exists and serializer is registered in a corresponding SerializersModule.
837*57b5a4a6SAndroid Build Coastguard Worker```
838*57b5a4a6SAndroid Build Coastguard Worker
839*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST LINES_START -->
840*57b5a4a6SAndroid Build Coastguard Worker
841*57b5a4a6SAndroid Build Coastguard WorkerWhen reading a flexible input we might want to provide some default behavior in this case. For example,
842*57b5a4a6SAndroid Build Coastguard Workerwe can have a `BasicProject` subtype to represent all kinds of unknown `Project` subtypes.
843*57b5a4a6SAndroid Build Coastguard Worker
844*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
845*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
846*57b5a4a6SAndroid Build Coastguard Worker-->
847*57b5a4a6SAndroid Build Coastguard Worker
848*57b5a4a6SAndroid Build Coastguard Worker```kotlin
849*57b5a4a6SAndroid Build Coastguard Worker@Serializable
850*57b5a4a6SAndroid Build Coastguard Workerabstract class Project {
851*57b5a4a6SAndroid Build Coastguard Worker    abstract val name: String
852*57b5a4a6SAndroid Build Coastguard Worker}
853*57b5a4a6SAndroid Build Coastguard Worker
854*57b5a4a6SAndroid Build Coastguard Worker@Serializable
855*57b5a4a6SAndroid Build Coastguard Workerdata class BasicProject(override val name: String, val type: String): Project()
856*57b5a4a6SAndroid Build Coastguard Worker
857*57b5a4a6SAndroid Build Coastguard Worker@Serializable
858*57b5a4a6SAndroid Build Coastguard Worker@SerialName("OwnedProject")
859*57b5a4a6SAndroid Build Coastguard Workerdata class OwnedProject(override val name: String, val owner: String) : Project()
860*57b5a4a6SAndroid Build Coastguard Worker```
861*57b5a4a6SAndroid Build Coastguard Worker
862*57b5a4a6SAndroid Build Coastguard WorkerWe register a default deserializer handler using the [`defaultDeserializer`][PolymorphicModuleBuilder.defaultDeserializer] function in
863*57b5a4a6SAndroid Build Coastguard Workerthe [`polymorphic { ... }`][PolymorphicModuleBuilder] DSL that defines a strategy which maps the `type` string from the input
864*57b5a4a6SAndroid Build Coastguard Workerto the [deserialization strategy][DeserializationStrategy]. In the below example we don't use the type,
865*57b5a4a6SAndroid Build Coastguard Workerbut always return the [Plugin-generated serializer](serializers.md#plugin-generated-serializer)
866*57b5a4a6SAndroid Build Coastguard Workerof the `BasicProject` class.
867*57b5a4a6SAndroid Build Coastguard Worker
868*57b5a4a6SAndroid Build Coastguard Worker```kotlin
869*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
870*57b5a4a6SAndroid Build Coastguard Worker    polymorphic(Project::class) {
871*57b5a4a6SAndroid Build Coastguard Worker        subclass(OwnedProject::class)
872*57b5a4a6SAndroid Build Coastguard Worker        defaultDeserializer { BasicProject.serializer() }
873*57b5a4a6SAndroid Build Coastguard Worker    }
874*57b5a4a6SAndroid Build Coastguard Worker}
875*57b5a4a6SAndroid Build Coastguard Worker```
876*57b5a4a6SAndroid Build Coastguard Worker
877*57b5a4a6SAndroid Build Coastguard WorkerUsing this module we can now deserialize both instances of the registered `OwnedProject` and
878*57b5a4a6SAndroid Build Coastguard Workerany unregistered one.
879*57b5a4a6SAndroid Build Coastguard Worker
880*57b5a4a6SAndroid Build Coastguard Worker```kotlin
881*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
882*57b5a4a6SAndroid Build Coastguard Worker
883*57b5a4a6SAndroid Build Coastguard Workerfun main() {
884*57b5a4a6SAndroid Build Coastguard Worker    println(format.decodeFromString<List<Project>>("""
885*57b5a4a6SAndroid Build Coastguard Worker        [
886*57b5a4a6SAndroid Build Coastguard Worker            {"type":"unknown","name":"example"},
887*57b5a4a6SAndroid Build Coastguard Worker            {"type":"OwnedProject","name":"kotlinx.serialization","owner":"kotlin"}
888*57b5a4a6SAndroid Build Coastguard Worker        ]
889*57b5a4a6SAndroid Build Coastguard Worker    """))
890*57b5a4a6SAndroid Build Coastguard Worker}
891*57b5a4a6SAndroid Build Coastguard Worker```
892*57b5a4a6SAndroid Build Coastguard Worker
893*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-19.kt).
894*57b5a4a6SAndroid Build Coastguard Worker
895*57b5a4a6SAndroid Build Coastguard WorkerNotice, how `BasicProject` had also captured the specified type key in its `type` property.
896*57b5a4a6SAndroid Build Coastguard Worker
897*57b5a4a6SAndroid Build Coastguard Worker```text
898*57b5a4a6SAndroid Build Coastguard Worker[BasicProject(name=example, type=unknown), OwnedProject(name=kotlinx.serialization, owner=kotlin)]
899*57b5a4a6SAndroid Build Coastguard Worker```
900*57b5a4a6SAndroid Build Coastguard Worker
901*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
902*57b5a4a6SAndroid Build Coastguard Worker
903*57b5a4a6SAndroid Build Coastguard WorkerWe used a plugin-generated serializer as a default serializer, implying that
904*57b5a4a6SAndroid Build Coastguard Workerthe structure of the "unknown" data is known in advance. In a real-world API it's rarely the case.
905*57b5a4a6SAndroid Build Coastguard WorkerFor that purpose a custom, less-structured serializer is needed. You will see the example of such serializer in the future section
906*57b5a4a6SAndroid Build Coastguard Workeron [Maintaining custom JSON attributes](json.md#maintaining-custom-json-attributes).
907*57b5a4a6SAndroid Build Coastguard Worker
908*57b5a4a6SAndroid Build Coastguard Worker### Default polymorphic type handler for serialization
909*57b5a4a6SAndroid Build Coastguard Worker
910*57b5a4a6SAndroid Build Coastguard WorkerSometimes you need to dynamically choose which serializer to use for a polymorphic type based on the instance, for example if you
911*57b5a4a6SAndroid Build Coastguard Workerdon't have access to the full type hierarchy, or if it changes a lot. For this situation, you can register a default serializer.
912*57b5a4a6SAndroid Build Coastguard Worker
913*57b5a4a6SAndroid Build Coastguard Worker<!--- INCLUDE
914*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.descriptors.*
915*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.encoding.*
916*57b5a4a6SAndroid Build Coastguard Workerimport kotlinx.serialization.modules.*
917*57b5a4a6SAndroid Build Coastguard Worker-->
918*57b5a4a6SAndroid Build Coastguard Worker
919*57b5a4a6SAndroid Build Coastguard Worker```kotlin
920*57b5a4a6SAndroid Build Coastguard Workerinterface Animal {
921*57b5a4a6SAndroid Build Coastguard Worker}
922*57b5a4a6SAndroid Build Coastguard Worker
923*57b5a4a6SAndroid Build Coastguard Workerinterface Cat : Animal {
924*57b5a4a6SAndroid Build Coastguard Worker    val catType: String
925*57b5a4a6SAndroid Build Coastguard Worker}
926*57b5a4a6SAndroid Build Coastguard Worker
927*57b5a4a6SAndroid Build Coastguard Workerinterface Dog : Animal {
928*57b5a4a6SAndroid Build Coastguard Worker    val dogType: String
929*57b5a4a6SAndroid Build Coastguard Worker}
930*57b5a4a6SAndroid Build Coastguard Worker
931*57b5a4a6SAndroid Build Coastguard Workerprivate class CatImpl : Cat {
932*57b5a4a6SAndroid Build Coastguard Worker    override val catType: String = "Tabby"
933*57b5a4a6SAndroid Build Coastguard Worker}
934*57b5a4a6SAndroid Build Coastguard Worker
935*57b5a4a6SAndroid Build Coastguard Workerprivate class DogImpl : Dog {
936*57b5a4a6SAndroid Build Coastguard Worker    override val dogType: String = "Husky"
937*57b5a4a6SAndroid Build Coastguard Worker}
938*57b5a4a6SAndroid Build Coastguard Worker
939*57b5a4a6SAndroid Build Coastguard Workerobject AnimalProvider {
940*57b5a4a6SAndroid Build Coastguard Worker    fun createCat(): Cat = CatImpl()
941*57b5a4a6SAndroid Build Coastguard Worker    fun createDog(): Dog = DogImpl()
942*57b5a4a6SAndroid Build Coastguard Worker}
943*57b5a4a6SAndroid Build Coastguard Worker```
944*57b5a4a6SAndroid Build Coastguard Worker
945*57b5a4a6SAndroid Build Coastguard WorkerWe register a default serializer handler using the [`polymorphicDefaultSerializer`][SerializersModuleBuilder.polymorphicDefaultSerializer] function in
946*57b5a4a6SAndroid Build Coastguard Workerthe [`SerializersModule { ... }`][SerializersModuleBuilder] DSL that defines a strategy which takes an instance of the base class and
947*57b5a4a6SAndroid Build Coastguard Workerprovides a [serialization strategy][SerializationStrategy]. In the below example we use a `when` block to check the type of the
948*57b5a4a6SAndroid Build Coastguard Workerinstance, without ever having to refer to the private implementation classes.
949*57b5a4a6SAndroid Build Coastguard Worker
950*57b5a4a6SAndroid Build Coastguard Worker```kotlin
951*57b5a4a6SAndroid Build Coastguard Workerval module = SerializersModule {
952*57b5a4a6SAndroid Build Coastguard Worker    polymorphicDefaultSerializer(Animal::class) { instance ->
953*57b5a4a6SAndroid Build Coastguard Worker        @Suppress("UNCHECKED_CAST")
954*57b5a4a6SAndroid Build Coastguard Worker        when (instance) {
955*57b5a4a6SAndroid Build Coastguard Worker            is Cat -> CatSerializer as SerializationStrategy<Animal>
956*57b5a4a6SAndroid Build Coastguard Worker            is Dog -> DogSerializer as SerializationStrategy<Animal>
957*57b5a4a6SAndroid Build Coastguard Worker            else -> null
958*57b5a4a6SAndroid Build Coastguard Worker        }
959*57b5a4a6SAndroid Build Coastguard Worker    }
960*57b5a4a6SAndroid Build Coastguard Worker}
961*57b5a4a6SAndroid Build Coastguard Worker
962*57b5a4a6SAndroid Build Coastguard Workerobject CatSerializer : SerializationStrategy<Cat> {
963*57b5a4a6SAndroid Build Coastguard Worker    override val descriptor = buildClassSerialDescriptor("Cat") {
964*57b5a4a6SAndroid Build Coastguard Worker        element<String>("catType")
965*57b5a4a6SAndroid Build Coastguard Worker    }
966*57b5a4a6SAndroid Build Coastguard Worker
967*57b5a4a6SAndroid Build Coastguard Worker    override fun serialize(encoder: Encoder, value: Cat) {
968*57b5a4a6SAndroid Build Coastguard Worker        encoder.encodeStructure(descriptor) {
969*57b5a4a6SAndroid Build Coastguard Worker          encodeStringElement(descriptor, 0, value.catType)
970*57b5a4a6SAndroid Build Coastguard Worker        }
971*57b5a4a6SAndroid Build Coastguard Worker    }
972*57b5a4a6SAndroid Build Coastguard Worker}
973*57b5a4a6SAndroid Build Coastguard Worker
974*57b5a4a6SAndroid Build Coastguard Workerobject DogSerializer : SerializationStrategy<Dog> {
975*57b5a4a6SAndroid Build Coastguard Worker  override val descriptor = buildClassSerialDescriptor("Dog") {
976*57b5a4a6SAndroid Build Coastguard Worker    element<String>("dogType")
977*57b5a4a6SAndroid Build Coastguard Worker  }
978*57b5a4a6SAndroid Build Coastguard Worker
979*57b5a4a6SAndroid Build Coastguard Worker  override fun serialize(encoder: Encoder, value: Dog) {
980*57b5a4a6SAndroid Build Coastguard Worker    encoder.encodeStructure(descriptor) {
981*57b5a4a6SAndroid Build Coastguard Worker      encodeStringElement(descriptor, 0, value.dogType)
982*57b5a4a6SAndroid Build Coastguard Worker    }
983*57b5a4a6SAndroid Build Coastguard Worker  }
984*57b5a4a6SAndroid Build Coastguard Worker}
985*57b5a4a6SAndroid Build Coastguard Worker```
986*57b5a4a6SAndroid Build Coastguard Worker
987*57b5a4a6SAndroid Build Coastguard WorkerUsing this module we can now serialize instances of `Cat` and `Dog`.
988*57b5a4a6SAndroid Build Coastguard Worker
989*57b5a4a6SAndroid Build Coastguard Worker```kotlin
990*57b5a4a6SAndroid Build Coastguard Workerval format = Json { serializersModule = module }
991*57b5a4a6SAndroid Build Coastguard Worker
992*57b5a4a6SAndroid Build Coastguard Workerfun main() {
993*57b5a4a6SAndroid Build Coastguard Worker    println(format.encodeToString<Animal>(AnimalProvider.createCat()))
994*57b5a4a6SAndroid Build Coastguard Worker}
995*57b5a4a6SAndroid Build Coastguard Worker```
996*57b5a4a6SAndroid Build Coastguard Worker
997*57b5a4a6SAndroid Build Coastguard Worker> You can get the full code [here](../guide/example/example-poly-20.kt)
998*57b5a4a6SAndroid Build Coastguard Worker
999*57b5a4a6SAndroid Build Coastguard Worker```text
1000*57b5a4a6SAndroid Build Coastguard Worker{"type":"Cat","catType":"Tabby"}
1001*57b5a4a6SAndroid Build Coastguard Worker```
1002*57b5a4a6SAndroid Build Coastguard Worker
1003*57b5a4a6SAndroid Build Coastguard Worker
1004*57b5a4a6SAndroid Build Coastguard Worker<!--- TEST -->
1005*57b5a4a6SAndroid Build Coastguard Worker
1006*57b5a4a6SAndroid Build Coastguard Worker---
1007*57b5a4a6SAndroid Build Coastguard Worker
1008*57b5a4a6SAndroid Build Coastguard WorkerThe next chapter covers [JSON features](json.md).
1009*57b5a4a6SAndroid Build Coastguard Worker
1010*57b5a4a6SAndroid Build Coastguard Worker<!--- MODULE /kotlinx-serialization-core -->
1011*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-core/kotlinx.serialization -->
1012*57b5a4a6SAndroid Build Coastguard Worker
1013*57b5a4a6SAndroid Build Coastguard Worker[SerialName]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serial-name/index.html
1014*57b5a4a6SAndroid Build Coastguard Worker[PolymorphicSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-polymorphic-serializer/index.html
1015*57b5a4a6SAndroid Build Coastguard Worker[Serializable]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializable/index.html
1016*57b5a4a6SAndroid Build Coastguard Worker[Polymorphic]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-polymorphic/index.html
1017*57b5a4a6SAndroid Build Coastguard Worker[DeserializationStrategy]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-deserialization-strategy/index.html
1018*57b5a4a6SAndroid Build Coastguard Worker[SerializationStrategy]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serialization-strategy/index.html
1019*57b5a4a6SAndroid Build Coastguard Worker
1020*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-core/kotlinx.serialization.modules -->
1021*57b5a4a6SAndroid Build Coastguard Worker
1022*57b5a4a6SAndroid Build Coastguard Worker[SerializersModule]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module/index.html
1023*57b5a4a6SAndroid Build Coastguard Worker[SerializersModule()]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module.html
1024*57b5a4a6SAndroid Build Coastguard Worker[_polymorphic]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/polymorphic.html
1025*57b5a4a6SAndroid Build Coastguard Worker[subclass]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/subclass.html
1026*57b5a4a6SAndroid Build Coastguard Worker[plus]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/plus.html
1027*57b5a4a6SAndroid Build Coastguard Worker[SerializersModuleBuilder.include]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module-builder/include.html
1028*57b5a4a6SAndroid Build Coastguard Worker[PolymorphicModuleBuilder.defaultDeserializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-polymorphic-module-builder/default-deserializer.html
1029*57b5a4a6SAndroid Build Coastguard Worker[PolymorphicModuleBuilder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-polymorphic-module-builder/index.html
1030*57b5a4a6SAndroid Build Coastguard Worker[SerializersModuleBuilder.polymorphicDefaultSerializer]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module-builder/polymorphic-default-serializer.html
1031*57b5a4a6SAndroid Build Coastguard Worker[SerializersModuleBuilder]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.modules/-serializers-module-builder/index.html
1032*57b5a4a6SAndroid Build Coastguard Worker
1033*57b5a4a6SAndroid Build Coastguard Worker<!--- MODULE /kotlinx-serialization-json -->
1034*57b5a4a6SAndroid Build Coastguard Worker<!--- INDEX kotlinx-serialization-json/kotlinx.serialization.json -->
1035*57b5a4a6SAndroid Build Coastguard Worker
1036*57b5a4a6SAndroid Build Coastguard Worker[Json.encodeToString]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/encode-to-string.html
1037*57b5a4a6SAndroid Build Coastguard Worker[Json]: https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/index.html
1038*57b5a4a6SAndroid Build Coastguard Worker
1039*57b5a4a6SAndroid Build Coastguard Worker<!--- END -->
1040*57b5a4a6SAndroid Build Coastguard Worker
1041