Skip to content

Commit

Permalink
Update documentation to reflect new modules and polymorphic system
Browse files Browse the repository at this point in the history
  • Loading branch information
sandwwraith committed Mar 22, 2019
1 parent 00cb67a commit 50e8af8
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 14 deletions.
31 changes: 20 additions & 11 deletions docs/custom_serializers.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ a generic class, this method will have arguments `KSerializer<T1>, KSerializer<T

## Table of contents

* [Customizing default serializer](#customizing)
* [External and generic serialization](#external-serializers-for-library-classes)
* [Customizing default serializers](#customizing)
- [Representing classes as a single value](#representing-classes-as-a-single-value)
- [Representing classes as multiple values](#representing-classes-as-multiple-values)
* [External serializers for library classes](#external-serializers-for-library-classes)
+ [About generic serializers](#about-generic-serializers)
* [Using custom serializers](#using-custom-serializers)

+ [`UseSerializers` annotation](#useserializers-annotation)
* [Registering and serial modules](#registering-and-context)
+ [`ContextualSerialization` annotation](#contextualserialization-annotation)

## Customizing

Expand Down Expand Up @@ -200,14 +205,18 @@ If you have a lot of serializable classes, which use, say `java.util.Date`, it m

By default, all serializers are resolved by plugin statically when compiling serializable class.
This gives us type-safety, performance and eliminates reflection usage to minimum. However, if there is no
`@Serializable` annotation of class and no `@Serializable(with=...)` on property, in general, it is impossible to know at compile time which serializer to
`@Serializable` annotation of class and no `@Serializable(with=...)` on property, in general,
it is impossible to know at compile time which serializer to
use - user can define more than one external serializer, or define them in other module, or even it's a class from
library which doesn't know anything about serialization.

To support such cases, a concept of `SerialContext` was introduced. Roughly speaking, it's a map where
To support such cases, a concept of `SerialModule` was introduced. Roughly speaking, it's a map where
runtime part of framework is looking for serializers if they weren't resolved at compile time by plugin.
Modules are intended to be reused in different formats or even different projects
(e.g. Library A have some custom serializers and exports a module with them so Application B can use A's classes with serializers in B's output).

If you want your external serializers to be used, you must register them in a context of serialization format. Registration is done via an _installation of modules_. Module is a bunch of serializers tied to classes. Modules are intended to be reused in different formats or even different projects (e.g. Library A have some custom serializers and exports a module with them so Application B can use A's classes with serializers in B's output).
If you want your external serializers to be used, you pass a module with them to the serialization format.
All standard formats have constructor parameter `context: SerialModule`.

### `ContextualSerialization` annotation

Expand All @@ -222,12 +231,12 @@ You can also install different modules for one class into different instances of
```kotlin
// Imagine we have class Payload with 2 different serializers

val simpleModule = SimpleModule(Payload::class, PayloadSerializer)
// MapModule and CompositeModule are also available
val binaryModule = SimpleModule(Payload::class, BinaryPayloadSerializer)
val simpleModule = serializersModuleOf(Payload::class, PayloadSerializer)
// You can also create modules from map or using a builder function SerializersModule { ... }
val binaryModule = serializersModuleOf(Payload::class, BinaryPayloadSerializer)

val json1 = Json().apply { install(simpleModule) }
val json2 = Json().apply { install(binaryModule) }
val json1 = Json(context = simpleModule)
val json2 = Json(context = binaryModule)

// in json1, Payload would be serialized with PayloadSerializer,
// in json2, Payload would be serialized with BinaryPayloadSerializer
Expand Down
1 change: 1 addition & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ still be mandatory and always present in serialized form.
```

To obtain serializers for root-level collections, you can use extension functions defined on serializers, like `.list` (see [this](https://github.com/Kotlin/kotlinx.serialization/issues/27) issue)

## User-defined serial annotations

In some cases, one may like to save additional format-specific information in the object itself. For example, protobuf field id.
Expand Down
43 changes: 40 additions & 3 deletions docs/runtime_usage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Runtime library contents and usage

* [Obtaining serializers](#obtaining-serializers)
+ [Implicit reflection serializers](#implicit-reflection-serializers)
+ [Special serializers](#special-serializers)
* [Serialization formats](#serialization-formats)
+ [JSON](#json)
+ [CBOR](#cbor)
+ [Protobuf](#protobuf)
* [Useful classes](#useful-classes)
+ [Mapper](#mapper)
+ [Dynamic object parser (JS only)](#dynamic-object-parser-js-only)


## Obtaining serializers

Serializers are represented at runtime as `KSerializer<T>`, which in turn, implements interfaces `SerializationStrategy<T>` and `DeserializationStrategy<T>`, where `T` is class you serialize.
Expand Down Expand Up @@ -32,13 +44,38 @@ val li: KSerializer<List<Data>> = Data.serializer().list
val mp: KSerializer<Map<String, Int>> = (StringSerializer to IntSerializer).map // extension on Pair of serializers
```

All external serializers (defined by user) are instantiated in a user-specific way. To learn how to write them, see [docs](custom_serializers.md).

### Implicit reflection serializers

In following special case:
* Class explicitly marked `@Serializable`
* Class doesn't have generic type arguments
* Class does not have generic type arguments

You can obtain serializer from KClass instance: `val d: KSerializer<MyData> = MyData::class.serializer()`. This approach is discouraged in general because of its implicitness, but maybe useful shorthand in some cases.
You can obtain serializer from KClass instance: `val d: KSerializer<MyData> = MyData::class.serializer()`.
This approach is discouraged in general because it is implicit and uses reflection (and therefore not working on Kotlin/Native),
but may be useful shorthand in some cases.

All external serializers (defined by user) are instantiated in a user-specific way. To learn how to write them, see [docs](custom_serializers.md).
Functions which uses this or similar functionality are annotated
with [experimental](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-experimental/index.html)
annotation `kotlinx.serialization.ImplicitReflectionSerializer`.
Consult [annotation documentation](https://github.com/kotlin/kotlinx.serialization/blob/master/runtime/common/src/main/kotlin/kotlinx/serialization/SerialImplicits.kt#L11)
to learn about restrictions of this approach.
To learn how to use experimental annotations, look at theirs [KEEP](https://github.com/Kotlin/KEEP/blob/master/proposals/experimental.md)
or use [this guide](https://kotlinlang.org/docs/reference/experimental.html#using-experimental-apis).

### Special serializers

There are two special serializers which are turned on using corresponding annotations:
`@Contextual` for `ContextSerializer` and `@Polymorphic` for `PolymorphicSerializer`.

The former allows to switch to the run-time resolving of serializers instead of compile-time.
This can be useful when you want to use some custom external serializer
or to define different serializers for different formats.
The latter allows polymorphic serialization and deserialization using runtime class information
and recorded name of a class. Consult theirs documentation for details.

Both use serial modules system, which is explained [here](custom_serializers.md#registering-and-context).

## Serialization formats

Expand Down

0 comments on commit 50e8af8

Please sign in to comment.