Skip to content

Commit

Permalink
Merge branch 'master' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
sandwwraith committed May 31, 2019
2 parents 490c751 + fe1fe4b commit 45241c1
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 40 deletions.
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,23 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**

**To Reproduce**
Attach a code snippet or test data if possible.

**Expected behavior**

**Environment**
- Kotlin version: [e.g. 1.3.30]
- Library version: [e.g. 0.11.0]
- Kotlin platforms: [e.g. JVM, JS, Native or their combinations]
- Gradle version: [e.g. 4.10]
- IDE version (if bug is related to the IDE) [e.g. IntellijIDEA 2019.1, Android Studio 3.4]
- Other relevant context [e.g. OS version, JRE version, ... ]
12 changes: 12 additions & 0 deletions .github/ISSUE_TEMPLATE/feature-request---design-discussion.md
@@ -0,0 +1,12 @@
---
name: Feature request / design discussion
about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''

---

**What is your use-case and why do you need this feature?**

**Describe the solution you'd like**
13 changes: 8 additions & 5 deletions README.md
Expand Up @@ -44,21 +44,24 @@ You can open example projects for [JS](examples/example-js), [JVM](examples/exam
```kotlin

import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.*

@Serializable
data class Data(val a: Int, val b: String = "42")

fun main(args: Array<String>) {
// Json also has .Default configuration which provides more reasonable settings,
// but is subject to change in future versions
val json = Json(JsonConfiguration.Stable)
// serializing objects
val jsonData = Json.stringify(Data.serializer(), Data(42))
val jsonData = json.stringify(Data.serializer(), Data(42))
// serializing lists
val jsonList = Json.stringify(Data.serializer().list, listOf(Data(42)))
val jsonList = json.stringify(Data.serializer().list, listOf(Data(42)))
println(jsonData) // {"a": 42, "b": "42"}
println(jsonList) // [{"a": 42, "b": "42"}]

// parsing data back
val obj = Json.parse(Data.serializer(), """{"a":42}""") // b is optional since it has default value
val obj = json.parse(Data.serializer(), """{"a":42}""") // b is optional since it has default value
println(obj) // Data(a=42, b="42")
}
```
Expand Down Expand Up @@ -268,5 +271,5 @@ Library version `0.11.0` requires Kotlin 1.3.30 and higher and incompatible with

## Troubleshooting IntelliJ IDEA

Serialization support should work out of the box, if you have 1.3.x Kotlin plugin installed. If you have Kotlin 1.3.10 or lower, you have to delegate build to Gradle (`Settings - Build, Execution, Deployment - Build Tools - Gradle - Runner -` tick `Delegate IDE build/run actions to gradle`). Starting from 1.3.11, no delegation is required.
Serialization support should work out of the box, if you have 1.3.x Kotlin plugin installed and have imported the project from Maven or Gradle with serialization enabled in their buildscripts. If you have Kotlin 1.3.10 or lower, you have to delegate build to Gradle (`Settings - Build, Execution, Deployment - Build Tools - Gradle - Runner -` tick `Delegate IDE build/run actions to gradle`). Starting from 1.3.11, no delegation is required.
In case of problems, force project re-import from Gradle.
2 changes: 1 addition & 1 deletion docs/custom_serializers.md
Expand Up @@ -71,7 +71,7 @@ First, we need to correctly fill-in descriptor so all formats would know about m
@Serializable
class BinaryPayload(val req: ByteArray, val res: ByteArray) {
@Serializer(forClass = BinaryPayload::class)
companion object : KSerializer<MyData> {
companion object : KSerializer<BinaryPayload> {
override val descriptor: SerialDescriptor = object : SerialClassDescImpl("BinaryPayload") {
init {
addElement("req") // req will have index 0
Expand Down
71 changes: 38 additions & 33 deletions docs/examples.md
@@ -1,6 +1,8 @@
# Serialization documentation and example cases

**Note**: Cases are presented here as a series of *unit-tests* using non-standard *unquoted* JSON for ease of presentation. Standards-compliant JSON is supported, too. Just replace `Json.unquoted` with plain `Json`.
**Note**: Cases are presented here as a series of *unit-tests* using non-standard *unquoted* JSON for ease of presentation.
It was created as `val json = Json(JsonConfiguration.Stable.copy(unquoted = true))`.
Standards-compliant JSON is supported, too. Just use `.Stable` or `.Default` configurations or create your own.

## Supported properties

Expand All @@ -12,13 +14,13 @@
val data = Data(1, 2)

// Serialize with internal serializer for Data class
assertEquals("{a:1,b:2}", Json.unquoted.stringify(data))
assertEquals(data, Json.parse<Data>("{a:1,b:2}"))
assertEquals("{a:1,b:2}", json.stringify(Data.serializer(), data))
assertEquals(data, Json.parse(Data.serializer(), "{a:1,b:2}"))

// Serialize with external serializer for Data class
@Serializer(forClass=Data::class)
object ExtDataSerializer
assertEquals("{a:1,b:2}", Json.unquoted.stringify(ExtDataSerializer, data))
assertEquals("{a:1,b:2}", json.stringify(ExtDataSerializer, data))
assertEquals(data, Json.parse(ExtDataSerializer, "{a:1,b:2}"))
```

Expand All @@ -33,28 +35,30 @@
override fun equals(other: Any?) = /*...*/
}

assertEquals("{a:1, b:42}", Json.unquoted.stringify(Data(1)))
assertEquals(Data(1), Json.unquoted.parse<Data>("{a:1, b:42}"))
assertEquals("{a:1, b:42}", json.stringify(Data.serializer(), Data(1)))
assertEquals(Data(1), json.parse(Data.serializer(), "{a:1, b:42}"))
```

* Property will be considered _optional_ if it has default value.
* Property will be considered _optional_ if it has default value (kotlin 1.3.30 or higher is required).

```kotlin
@Serializable
data class Data(val a: Int, val b: Int = 42)

// Serialization and deserialization with internal serializer
assertEquals("{a:0,b:42}",Json.unquoted.stringify(Data(0)))
assertEquals(Json.unquoted.parse<Data>("{a:0,b:43}"),Data(b = 43))
assertEquals(Json.unquoted.parse<Data>("{a:0,b:42}"),Data(0))
assertEquals(Json.unquoted.parse<Data>("{a:0}"),Data(0))
assertEquals("{a:0,b:42}",json.stringify(Data.serializer(), Data(0)))
assertEquals(json.parse(Data.serializer(), "{a:0,b:43}"),Data(0, b = 43))
assertEquals(json.parse(Data.serializer(), "{a:0,b:42}"),Data(0))
assertEquals(json.parse(Data.serializer(), "{a:0}"),Data(0))

// This will throw SerializationException, because 'a' is missing.
Json.unquoted.parse<Data>("{b:0}")
json.parse(Data.serializer(), "{b:0}")
```

> Tip: you can omit default values during serialization with
`Json(encodeDefaults = false)` (see [here](runtime_usage#json)).
`Json(encodeDefaults = false)` (see [here](runtime_usage.md#json)).

> Tip: Deprecated `@Optional` annotation was used in older version and older kotlin version.

* By default, only properties which have
Expand All @@ -69,7 +73,7 @@
}

// b is not in serialized form!
assertEquals("{a:1}", Json.unquoted.stringify(Data(1)))
assertEquals("{a:1}", json.stringify(Data.serializer(), Data(1)))
```

You should be careful with this, especially when you have hierarchy of serializable classes with several overrides.
Expand All @@ -91,7 +95,7 @@
}

// prints nothing.
val data = Json.unquoted.parse<Data>("{a: 100500, b: 10}")
val data = json.parse(Data.serializer(), "{a: 100500, b: 10}")
```

* Initializers are called iff (if and only if) property is `@Transient` or optional and was not read (see below).
Expand All @@ -108,8 +112,8 @@
}

// prints "I'm a side effect" once.
val data = Json.unquoted.parse<Data>("{a: 100500, b: 10}")
val data = Json.unquoted.parse<Data>("{a: 100500}")
val data = json.parse(Data.serializer(), "{a: 100500, b: 10}")
val data = json.parse(Data.serializer(), "{a: 100500}")
```

* *Common pattern*: Validation.
Expand Down Expand Up @@ -155,7 +159,7 @@
@Serializer(forClass=Data::class)
object ExtDataSerializer

assertEquals("{a:1,b:2}", Json.unquoted.stringify(ExtDataSerializer, data))
assertEquals("{a:1,b:2}", json.stringify(ExtDataSerializer, data))
assertEquals(data, Json.parse(ExtDataSerializer, "{a:1,b:2}"))
```

Expand All @@ -174,7 +178,7 @@
val custom2: Int
)

assertEquals("{value1: a, value2: 42}", Json.unquoted.stringify(Names("a", 42)))
assertEquals("{value1: a, value2: 42}", json.stringify(Names.serializer(), Names("a", 42)))
```

> Starting from 0.6, `@SerialName` can be used on classes, too.
Expand All @@ -192,14 +196,14 @@ still be mandatory and always present in serialized form.

// Serialization and deserialization with internal serializer
// External serializer also supported
assertEquals("{a:0,b:42,c:Hello}",Json.unquoted.stringify(Data()))
assertEquals(Json.unquoted.parse<Data>("{a:0,b:43,c:Hello}"),Data(b = 43))
assertEquals(Json.unquoted.parse<Data>("{a:0,b:42,c:Hello}"),Data())
assertEquals(Json.unquoted.parse<Data>("{a:0,c:Hello}"),Data())
assertEquals(Json.unquoted.parse<Data>("{a:0}"),Data())
assertEquals("{a:0,b:42,c:Hello}",json.stringify(Data.serializer(), Data()))
assertEquals(json.parse(Data.serializer(), "{a:0,b:43,c:Hello}"), Data(b = 43))
assertEquals(json.parse(Data.serializer(), "{a:0,b:42,c:Hello}"), Data())
assertEquals(json.parse(Data.serializer(), "{a:0,c:Hello}"), Data())
assertEquals(json.parse(Data.serializer(), "{a:0}"), Data())

// This will throw SerializationException, because 'a' is missing.
Json.unquoted.parse<Data>("{b:0}")
json.parse(Data.serializer(), "{b:0}")
```

* `@Transient` annotation for supported properties. This annotation excludes marked properties from process of serialization or deserialization. Requires default value. *Don't confuse with `kotlin.jvm.Transient`!*
Expand All @@ -217,14 +221,14 @@ still be mandatory and always present in serialized form.

// Serialization and deserialization with internal serializer
// External serializer also supported
assertEquals("{a:0,c:Hello}",Json.unquoted.stringify(Data()))
assertEquals(Json.unquoted.parse<Data>("{a:0,c:Hello}"),Data())
assertEquals(Json.unquoted.parse<Data>("{a:0}"),Data())
assertEquals("{a:0,c:Hello}",json.stringify(Data.serializer(), Data()))
assertEquals(json.parse(Data.serializer(), "{a:0,c:Hello}"), Data())
assertEquals(json.parse(Data.serializer(), "{a:0}"), Data())


// This will throw SerializationException, because
// property 'b' is unknown to deserializer.
Json.unquoted.parse<Data>("{a:0,b:100500,c:Hello}")
json.parse(Data.serializer(), "{a:0,b:100500,c:Hello}")
```

* Initializing `@Transient` or optional fields in init blocks is not supported.
Expand All @@ -250,14 +254,15 @@ still be mandatory and always present in serialized form.
val prop by myMap
}

assertEquals("value", Json.unquoted.parse<WithDelegates>("{myMap:{prop:value}}").prop)
assertEquals("value", json.parse(WithDelegates.serializer(), "{myMap:{prop:value}}").prop)
```

## Nesting

* Nested values are recursively serialized, enums, primitive types, arrays, lists and maps are supported, plus other serializable classes.

```kotlin
// Enums are implicitly @Serializable
enum class TintEnum { LIGHT, DARK }

@Serializable
Expand All @@ -269,13 +274,13 @@ still be mandatory and always present in serialized form.
val data = Data("Str", listOf(1, 2), mapOf("lt" to TintEnum.LIGHT, "dk" to TintEnum.DARK))

// Serialize with internal serializer for Data class
assertEquals("{a:Str,b:[1,2],c:{lt:LIGHT,dk:DARK}}", Json.unquoted.stringify(data))
assertEquals(data, Json.parse<Data>("{a:Str,b:[1,2],c:{lt:LIGHT,dk:DARK}}"))
assertEquals("{a:Str,b:[1,2],c:{lt:LIGHT,dk:DARK}}", json.stringify(Data.serializer(), data))
assertEquals(data, Json.parse("{a:Str,b:[1,2],c:{lt:LIGHT,dk:DARK}}"))

// Serialize with external serializer for Data class
@Serializer(forClass=Data::class)
object ExtDataSerializer
assertEquals("{a:Str,b:[1,2],c:{lt:LIGHT,dk:DARK}}", Json.unquoted.stringify(ExtDataSerializer, data))
assertEquals("{a:Str,b:[1,2],c:{lt:LIGHT,dk:DARK}}", json.stringify(ExtDataSerializer, data))
assertEquals(data, Json.parse(ExtDataSerializer, "{a:Str,b:[1,2],c:{lt:LIGHT,dk:DARK}}"))
```

Expand Down
2 changes: 1 addition & 1 deletion docs/runtime_usage.md
Expand Up @@ -97,7 +97,7 @@ It is configurable via `JsonConfiguration` class, which has following parameters
It also has two pre-defined sets of parameters: `Default` and `Stable`.
`Default` provides recommended and sane configuration, however, due to a library evolution,
it can be tweaked and changed between library releases.
`Stable` provides backwards-compatible configuration, e.g. `useArrayPolymorphism` is set to `true` in it because early library versions have used this format.
`Stable` provides configuration which is guaranteed to be unchanged between library releases.
Since `JsonConfiguration` is a data class, you can `copy` any configuration you like to tweak it.

All unstable constructors and configurations are annotated with [experimental annotation](https://kotlinlang.org/docs/reference/experimental.html#using-experimental-apis) `kotlinx.serialization.UnstableDefault`.
Expand Down

0 comments on commit 45241c1

Please sign in to comment.