1 /* 2 * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 @file:Suppress("EqualsOrHashCode") 6 7 package kotlinx.serialization.features 8 9 import kotlinx.serialization.* 10 import kotlinx.serialization.json.* 11 import kotlinx.serialization.test.* 12 import kotlin.test.* 13 14 @Serializable 15 abstract class AbstractSerializable { 16 public abstract val rootState: String // no backing field 17 18 val publicState: String = "A" 19 } 20 21 @Serializable 22 open class SerializableBase: AbstractSerializable() { 23 24 25 private val privateState: String = "B" // still should be serialized 26 27 @Transient 28 private val privateTransientState = "C" // not serialized: explicitly transient 29 30 val notAState: String // not serialized: no backing field 31 get() = "D" 32 33 override val rootState: String 34 get() = "E" // still not serializable 35 equalsnull36 override fun equals(other: Any?): Boolean { 37 if (this === other) return true 38 if (other !is SerializableBase) return false 39 40 if (privateState != other.privateState) return false 41 if (privateTransientState != other.privateTransientState) return false 42 43 return true 44 } 45 } 46 47 @Serializable 48 class Derived(val derivedState: Int): SerializableBase() { 49 override val rootState: String = "foo" // serializable! 50 equalsnull51 override fun equals(other: Any?): Boolean { 52 if (this === other) return true 53 if (other !is Derived) return false 54 if (!super.equals(other)) return false 55 56 if (derivedState != other.derivedState) return false 57 if (rootState != other.rootState) return false 58 59 return true 60 } 61 } 62 63 @Serializable 64 open class Base1(open var state1: String) { toStringnull65 override fun toString(): String { 66 return "Base1(state1='$state1')" 67 } 68 } 69 70 @Serializable 71 class Derived2(@SerialName("state2") override var state1: String): Base1(state1) { toStringnull72 override fun toString(): String { 73 return "Derived2(state1='$state1')" 74 } 75 } 76 77 class InheritanceTest { <lambda>null78 private val json = Json { encodeDefaults = true } 79 80 @Test canBeSerializedAsDerivednull81 fun canBeSerializedAsDerived() { 82 val derived = Derived(42) 83 val msg = json.encodeToString(Derived.serializer(), derived) 84 assertEquals("""{"publicState":"A","privateState":"B","derivedState":42,"rootState":"foo"}""", msg) 85 val d2 = json.decodeFromString(Derived.serializer(), msg) 86 assertEquals(derived, d2) 87 } 88 89 @Test canBeSerializedAsParentnull90 fun canBeSerializedAsParent() { 91 val derived = Derived(42) 92 val msg = json.encodeToString(SerializableBase.serializer(), derived) 93 assertEquals("""{"publicState":"A","privateState":"B"}""", msg) 94 val d2 = json.decodeFromString(SerializableBase.serializer(), msg) 95 assertEquals(SerializableBase(), d2) 96 // no derivedState 97 assertFailsWithMissingField { json.decodeFromString(Derived.serializer(), msg) } 98 } 99 100 @Test testWithOpenPropertynull101 fun testWithOpenProperty() { 102 val d = Derived2("foo") 103 val msgFull = json.encodeToString(Derived2.serializer(), d) 104 assertEquals("""{"state1":"foo","state2":"foo"}""", msgFull) 105 assertEquals("""{"state1":"foo"}""", json.encodeToString(Base1.serializer(), d)) 106 val restored = json.decodeFromString(Derived2.serializer(), msgFull) 107 val restored2 = json.decodeFromString(Derived2.serializer(), """{"state1":"bar","state2":"foo"}""") // state1 is ignored anyway 108 assertEquals("""Derived2(state1='foo')""", restored.toString()) 109 assertEquals("""Derived2(state1='foo')""", restored2.toString()) 110 } 111 } 112 113 114 115 116