commonTest.kotlinx.serialization.SerializersLookupTest.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlinx-serialization-json
Show all versions of kotlinx-serialization-json
Kotlin multiplatform serialization runtime library
/*
* Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.serialization
import kotlinx.serialization.builtins.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.features.sealed.SealedChild
import kotlinx.serialization.features.sealed.SealedParent
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*
import kotlinx.serialization.test.*
import kotlin.reflect.*
import kotlin.test.*
@Suppress("RemoveExplicitTypeArguments") // This is exactly what's being tested
class SerializersLookupTest : JsonTestBase() {
@Test
fun testPrimitive() {
val token = typeOf()
val serial = serializer(token)
assertSame(Int.serializer() as KSerializer<*>, serial)
assertSerializedWithType("42", 42)
}
@Test
fun testPlainClass() {
val b = StringData("some string")
assertSerializedWithType("""{"data":"some string"}""", b)
}
@Test
fun testListWithT() {
val source = """[{"intV":42}]"""
val serial = serializer>()
assertEquals(listOf(IntData(42)), Json.decodeFromString(serial, source))
}
@Test
fun testPrimitiveList() {
val myArr = listOf("a", "b", "c")
assertSerializedWithType("""["a","b","c"]""", myArr)
}
@Test
fun testListAsCollection() {
val myArr: Collection = listOf("a", "b", "c")
assertSerializedWithType("""["a","b","c"]""", myArr)
}
@Test
fun testPrimitiveSet() {
val mySet = setOf("a", "b", "c", "c")
assertSerializedWithType("""["a","b","c"]""", mySet)
}
@Test
fun testMapWithT() {
val myMap = mapOf("string" to StringData("foo"), "string2" to StringData("bar"))
assertSerializedWithType("""{"string":{"data":"foo"},"string2":{"data":"bar"}}""", myMap)
}
@Test
fun testNestedLists() {
val myList = listOf(listOf(listOf(1, 2, 3)), listOf())
assertSerializedWithType("[[[1,2,3]],[]]", myList)
}
@Test
fun testListSubtype() {
val myList = arrayListOf(1, 2, 3)
assertSerializedWithType>("[1,2,3]", myList)
assertSerializedWithType>("[1,2,3]", myList)
}
@Test
fun testListProjection() {
val myList = arrayListOf(1, 2, 3)
assertSerializedWithType>("[1,2,3]", myList)
assertSerializedWithType>("[1,2,3]", myList)
assertSerializedWithType>("[1,2,3]", myList)
}
@Test
fun testNullableTypes() {
val myList: List = listOf(1, null, 3)
assertSerializedWithType("[1,null,3]", myList)
assertSerializedWithType?>("[1,null,3]", myList)
}
@Test
fun testPair() {
val myPair = "42" to 42
assertSerializedWithType("""{"first":"42","second":42}""", myPair)
}
@Test
fun testTriple() = noLegacyJs { // because of Box
val myTriple = Triple("1", 2, Box(42))
assertSerializedWithType("""{"first":"1","second":2,"third":{"boxed":42}}""", myTriple)
}
@Test
fun testCustomGeneric() = noLegacyJs {
val intBox = Box(42)
val intBoxSerializer = serializer>()
assertEquals(Box.serializer(Int.serializer()).descriptor, intBoxSerializer.descriptor)
assertSerializedWithType("""{"boxed":42}""", intBox)
val dataBox = Box(StringData("foo"))
assertSerializedWithType("""{"boxed":{"data":"foo"}}""", dataBox)
}
@Test
fun testRecursiveGeneric() = noLegacyJs {
val boxBox = Box(Box(Box(IntData(42))))
assertSerializedWithType("""{"boxed":{"boxed":{"boxed":{"intV":42}}}}""", boxBox)
}
@Test
fun testMixedGeneric() = noLegacyJs {
val listOfBoxes = listOf(Box("foo"), Box("bar"))
assertSerializedWithType("""[{"boxed":"foo"},{"boxed":"bar"}]""", listOfBoxes)
val boxedList = Box(listOf("foo", "bar"))
assertSerializedWithType("""{"boxed":["foo","bar"]}""", boxedList)
}
@Test
fun testReferenceArrays() {
assertSerializedWithType("[1,2,3]", Array(3) { it + 1 }, default)
assertSerializedWithType("""["1","2","3"]""", Array(3) { (it + 1).toString() }, default)
assertSerializedWithType("[[0],[1],[2]]", Array>(3) { cnt -> Array(1) { cnt } }, default)
noLegacyJs {
assertSerializedWithType("""[{"boxed":"foo"}]""", Array(1) { Box("foo") }, default)
assertSerializedWithType("""[[{"boxed":"foo"}]]""", Array(1) { Array(1) { Box("foo") } }, default)
}
}
@Test
fun testPrimitiveArrays() {
assertSerializedWithType("[1,2,3]", intArrayOf(1, 2, 3), default)
assertSerializedWithType("[1,2,3]", longArrayOf(1, 2, 3), default)
assertSerializedWithType("[1,2,3]", byteArrayOf(1, 2, 3), default)
assertSerializedWithType("[1,2,3]", shortArrayOf(1, 2, 3), default)
assertSerializedWithType("[true,false]", booleanArrayOf(true, false), default)
assertSerializedWithType("""["a","b","c"]""", charArrayOf('a', 'b', 'c'), default)
}
@Test
fun testSerializableObject() = noLegacyJs {
assertSerializedWithType("{}", SampleObject)
}
class IntBox(val i: Int)
class CustomIntSerializer(isNullable: Boolean) : KSerializer {
override val descriptor: SerialDescriptor
init {
val d = PrimitiveSerialDescriptor("CIS", PrimitiveKind.INT)
descriptor = if (isNullable) d.nullable else d
}
override fun serialize(encoder: Encoder, value: IntBox?) {
if (value == null) encoder.encodeInt(41)
else encoder.encodeInt(42)
}
override fun deserialize(decoder: Decoder): IntBox? {
TODO()
}
}
@Test
fun testContextualLookup() {
val module = SerializersModule { contextual(CustomIntSerializer(false).cast()) }
val json = Json { serializersModule = module }
val data = listOf(listOf(IntBox(1)))
assertEquals("[[42]]", json.encodeToString(data))
}
@Test
fun testContextualLookupNullable() {
val module = SerializersModule { contextual(CustomIntSerializer(true).cast()) }
val serializer = module.serializer>>()
assertEquals("[[41]]", Json.encodeToString(serializer, listOf(listOf(null))))
}
@Test
fun testContextualLookupNonNullable() {
val module = SerializersModule { contextual(CustomIntSerializer(false).cast()) }
val serializer = module.serializer>>()
assertEquals("[[null]]", Json.encodeToString(serializer, listOf(listOf(null))))
}
@Test
fun testCompiledWinsOverContextual() {
val contextual = object : KSerializer {
override val descriptor: SerialDescriptor = Int.serializer().descriptor
override fun serialize(encoder: Encoder, value: Int) {
fail()
}
override fun deserialize(decoder: Decoder): Int {
fail()
}
}
val json = Json { serializersModule = SerializersModule { contextual(contextual) } }
assertEquals("[[1]]", json.encodeToString(listOf(listOf(1))))
assertEquals("42", json.encodeToString(42))
}
class NonSerializable
class NonSerializableBox(val boxed: T)
@Test
fun testSealedFromOtherFileLookup() {
assertNotNull(serializerOrNull(typeOf()))
assertNotNull(serializerOrNull(typeOf()))
}
@Test
fun testLookupFail() {
assertNull(serializerOrNull(typeOf()))
assertNull(serializerOrNull(typeOf>()))
assertNull(serializerOrNull(typeOf>()))
assertFailsWithMessage("for class 'NonSerializable'") {
serializer(typeOf())
}
assertFailsWithMessage("for class 'NonSerializableBox'") {
serializer(typeOf>())
}
assertFailsWithMessage("for class 'NonSerializable'") {
serializer(typeOf>())
}
}
private inline fun assertSerializedWithType(
expected: String,
value: T,
json: StringFormat = default
) {
val serial = serializer()
assertEquals(expected, json.encodeToString(serial, value))
val serial2 = requireNotNull(serializerOrNull(typeOf())) { "Expected serializer to be found" }
assertEquals(expected, json.encodeToString(serial2, value))
}
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun KSerializer<*>.cast(): KSerializer = this as KSerializer
}