From cc2a337deecf4f66040d1702a97de1734a78d843 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 2 Jan 2022 15:16:36 +0900 Subject: [PATCH 1/8] add tests --- .../module/kotlin/test/github/GitHub530.kt | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt new file mode 100644 index 000000000..6bacaa2c5 --- /dev/null +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt @@ -0,0 +1,83 @@ +package com.fasterxml.jackson.module.kotlin.test.github + +import com.fasterxml.jackson.annotation.JsonValue +import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder +import org.junit.Test +import kotlin.test.assertEquals + +class GitHub530 { + // At the moment, the output is the same with or without `JsonValue`, + // but this pattern is included in the test case in case the option to default to a serialization method that + // does not `unbox` is introduced in the future. + @JvmInline value class Foo(@get:JsonValue val value: Int) + @JvmInline value class Bar(@JvmField @field:JsonValue val value: Int) + + @JvmInline value class Baz(val value: Int) { + @get:JsonValue val jsonValue: String get() = this.toString() + } + @JvmInline value class Qux(val value: Int) { + @JsonValue fun getJsonValue(): String = this.toString() + } + + interface JsonValueGetter { @get:JsonValue val jsonValue: String get() = this.toString() } + @JvmInline value class Quux(val value: Int): JsonValueGetter + @JvmInline value class Corge(val value: Int): JsonValueGetter + + @JvmInline value class Grault(val value: Int) { + @get:JsonValue val jsonValue: String get() = this.toString() + } + + data class Data( + val foo1: Foo, + val foo2: Foo?, + val bar1: Bar, + val bar2: Bar?, + val baz1: Baz, + val baz2: Baz?, + val qux1: Qux, + val qux2: Qux?, + val quux1: Quux, + val quux2: Quux?, + val corge1: JsonValueGetter, + val corge2: JsonValueGetter?, + val grault1: T, + val grault2: T? + ) + + @Test + fun test() { + val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() + + assertEquals( + """ + { + "foo1" : 0, + "foo2" : 1, + "bar1" : 2, + "bar2" : 3, + "baz1" : "Baz(value=4)", + "baz2" : "Baz(value=5)", + "qux1" : "Qux(value=6)", + "qux2" : "Qux(value=7)", + "quux1" : "Quux(value=8)", + "quux2" : "Quux(value=9)", + "corge1" : "Corge(value=10)", + "corge2" : "Corge(value=11)", + "grault1" : "Grault(value=12)", + "grault2" : "Grault(value=13)", + } + """.trimIndent(), + writer.writeValueAsString( + Data( + Foo(0), Foo(1), + Bar(2), Bar(3), + Baz(4), Baz(5), + Qux(6), Qux(7), + Quux(8), Quux(9), + Corge(10), Corge(11), + Grault(12), Grault(13) + ) + ) + ) + } +} From b1cd3cff50e6fd1a108c7f4fec390703b8bb326a Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 2 Jan 2022 15:39:05 +0900 Subject: [PATCH 2/8] fix for unboxed cases --- .../kotlin/KotlinAnnotationIntrospector.kt | 9 ++++-- .../module/kotlin/KotlinSerializers.kt | 32 ++++++++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinAnnotationIntrospector.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinAnnotationIntrospector.kt index bb99dd8ef..f674699f3 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinAnnotationIntrospector.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinAnnotationIntrospector.kt @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.Module import com.fasterxml.jackson.databind.cfg.MapperConfig import com.fasterxml.jackson.databind.introspect.* import com.fasterxml.jackson.databind.jsontype.NamedType +import com.fasterxml.jackson.databind.ser.std.StdSerializer import java.lang.reflect.AccessibleObject import java.lang.reflect.Constructor import java.lang.reflect.Field @@ -62,7 +63,7 @@ internal class KotlinAnnotationIntrospector(private val context: Module.SetupCon } // Find a serializer to handle the case where the getter returns an unboxed value from the value class. - override fun findSerializer(am: Annotated): ValueClassBoxSerializer<*>? = when (am) { + override fun findSerializer(am: Annotated): StdSerializer<*>? = when (am) { is AnnotatedMethod -> { val getter = am.member.apply { // If the return value of the getter is a value class, @@ -87,8 +88,10 @@ internal class KotlinAnnotationIntrospector(private val context: Module.SetupCon ?.takeIf { it.isValue } ?.java ?.let { outerClazz -> - @Suppress("UNCHECKED_CAST") - ValueClassBoxSerializer(outerClazz, getter.returnType) + val innerClazz = getter.returnType + + ValueClassStaticJsonValueSerializer.createdOrNull(outerClazz, innerClazz) + ?: @Suppress("UNCHECKED_CAST") ValueClassBoxSerializer(outerClazz, innerClazz) } } // Ignore the case of AnnotatedField, because JvmField cannot be set in the field of value class. diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt index 2c27cc7f3..801ba7d84 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt @@ -1,5 +1,6 @@ package com.fasterxml.jackson.module.kotlin +import com.fasterxml.jackson.annotation.JsonValue import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.databind.BeanDescription import com.fasterxml.jackson.databind.JavaType @@ -8,8 +9,9 @@ import com.fasterxml.jackson.databind.SerializationConfig import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.ser.Serializers import com.fasterxml.jackson.databind.ser.std.StdSerializer +import java.lang.reflect.Method +import java.lang.reflect.Modifier import java.math.BigInteger -import kotlin.reflect.KClass object SequenceSerializer : StdSerializer>(Sequence::class.java) { override fun serialize(value: Sequence<*>, gen: JsonGenerator, provider: SerializerProvider) { @@ -43,6 +45,10 @@ object ULongSerializer : StdSerializer(ULong::class.java) { } } +// Class must be UnboxableValueClass. +private fun Class<*>.getStaticJsonValueGetter(): Method? = this.declaredMethods + .find { method -> Modifier.isStatic(method.modifiers) && method.annotations.any { it is JsonValue } } + object ValueClassUnboxSerializer : StdSerializer(Any::class.java) { override fun serialize(value: Any, gen: JsonGenerator, provider: SerializerProvider) { val unboxed = value::class.java.getMethod("unbox-impl").invoke(value) @@ -89,3 +95,27 @@ internal class ValueClassBoxSerializer( provider.findValueSerializer(outerClazz).serialize(boxed, gen, provider) } } + +internal class ValueClassStaticJsonValueSerializer private constructor( + innerClazz: Class, + private val staticJsonValueGetter: Method +) : StdSerializer(innerClazz) { + override fun serialize(value: T?, gen: JsonGenerator, provider: SerializerProvider) { + // As shown in the processing of the factory function, jsonValueGetter is always a static method. + val jsonValue: Any? = staticJsonValueGetter.invoke(null, value) + jsonValue + ?.let { provider.findValueSerializer(it::class.java).serialize(it, gen, provider) } + ?: provider.findNullValueSerializer(null).serialize(null, gen, provider) + } + + // Since JsonValue can be processed correctly if it is given to a non-static getter/field, + // this class will only process if it is a `static` method. + companion object { + fun createdOrNull( + outerClazz: Class, + innerClazz: Class + ): ValueClassStaticJsonValueSerializer? = outerClazz + .getStaticJsonValueGetter() + ?.let { ValueClassStaticJsonValueSerializer(innerClazz, it) } + } +} From 02fea55459f89983492ca9256b1d24bfea3455e1 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 2 Jan 2022 15:51:48 +0900 Subject: [PATCH 3/8] fix test --- .../fasterxml/jackson/module/kotlin/test/github/GitHub530.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt index 6bacaa2c5..831ad2de3 100644 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt @@ -64,7 +64,7 @@ class GitHub530 { "corge1" : "Corge(value=10)", "corge2" : "Corge(value=11)", "grault1" : "Grault(value=12)", - "grault2" : "Grault(value=13)", + "grault2" : "Grault(value=13)" } """.trimIndent(), writer.writeValueAsString( From 756d5448ee7e4a32d952766c62475f6b86700246 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 2 Jan 2022 15:59:48 +0900 Subject: [PATCH 4/8] fix for boxed cases --- .../module/kotlin/KotlinSerializers.kt | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt index 801ba7d84..a5aea09ad 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt @@ -49,16 +49,43 @@ object ULongSerializer : StdSerializer(ULong::class.java) { private fun Class<*>.getStaticJsonValueGetter(): Method? = this.declaredMethods .find { method -> Modifier.isStatic(method.modifiers) && method.annotations.any { it is JsonValue } } -object ValueClassUnboxSerializer : StdSerializer(Any::class.java) { - override fun serialize(value: Any, gen: JsonGenerator, provider: SerializerProvider) { - val unboxed = value::class.java.getMethod("unbox-impl").invoke(value) +internal sealed class ValueClassSerializer(t: Class) : StdSerializer(t) { + object Unbox : ValueClassSerializer(Any::class.java) { + override fun serialize(value: Any, gen: JsonGenerator, provider: SerializerProvider) { + val unboxed = value::class.java.getMethod("unbox-impl").invoke(value) - if (unboxed == null) { - provider.findNullValueSerializer(null).serialize(unboxed, gen, provider) - return + if (unboxed == null) { + provider.findNullValueSerializer(null).serialize(unboxed, gen, provider) + return + } + + provider.findValueSerializer(unboxed::class.java).serialize(unboxed, gen, provider) + } + } + + class StaticJsonValue( + t: Class, private val staticJsonValueGetter: Method + ) : ValueClassSerializer(t) { + private val unboxMethod: Method = t.getMethod("unbox-impl") + + override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) { + val unboxed = unboxMethod.invoke(value) + // As shown in the processing of the factory function, jsonValueGetter is always a static method. + val jsonValue: Any? = staticJsonValueGetter.invoke(null, unboxed) + jsonValue + ?.let { provider.findValueSerializer(it::class.java).serialize(it, gen, provider) } + ?: provider.findNullValueSerializer(null).serialize(null, gen, provider) } + } - provider.findValueSerializer(unboxed::class.java).serialize(unboxed, gen, provider) + companion object { + // `t` must be UnboxableValueClass. + // If create a function with a JsonValue in the value class, + // it will be compiled as a static method (= cannot be processed properly by Jackson), + // so use a ValueClassSerializer.StaticJsonValue to handle this. + fun from(t: Class<*>): ValueClassSerializer<*> = t.getStaticJsonValueGetter() + ?.let { StaticJsonValue(t, it) } + ?: Unbox } } @@ -74,7 +101,7 @@ internal class KotlinSerializers : Serializers.Base() { UInt::class.java.isAssignableFrom(type.rawClass) -> UIntSerializer ULong::class.java.isAssignableFrom(type.rawClass) -> ULongSerializer // The priority of Unboxing needs to be lowered so as not to break the serialization of Unsigned Integers. - type.rawClass.isUnboxableValueClass() -> ValueClassUnboxSerializer + type.rawClass.isUnboxableValueClass() -> ValueClassSerializer.from(type.rawClass) else -> null } } From 14a1244c6011c8863f7433c60369400315956d1e Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 2 Jan 2022 16:01:23 +0900 Subject: [PATCH 5/8] refactor --- .../module/kotlin/KotlinSerializers.kt | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt index a5aea09ad..305de370b 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt @@ -94,15 +94,19 @@ internal class KotlinSerializers : Serializers.Base() { config: SerializationConfig?, type: JavaType, beanDesc: BeanDescription? - ): JsonSerializer<*>? = when { - Sequence::class.java.isAssignableFrom(type.rawClass) -> SequenceSerializer - UByte::class.java.isAssignableFrom(type.rawClass) -> UByteSerializer - UShort::class.java.isAssignableFrom(type.rawClass) -> UShortSerializer - UInt::class.java.isAssignableFrom(type.rawClass) -> UIntSerializer - ULong::class.java.isAssignableFrom(type.rawClass) -> ULongSerializer - // The priority of Unboxing needs to be lowered so as not to break the serialization of Unsigned Integers. - type.rawClass.isUnboxableValueClass() -> ValueClassSerializer.from(type.rawClass) - else -> null + ): JsonSerializer<*>? { + val rawClass = type.rawClass + + return when { + Sequence::class.java.isAssignableFrom(rawClass) -> SequenceSerializer + UByte::class.java.isAssignableFrom(rawClass) -> UByteSerializer + UShort::class.java.isAssignableFrom(rawClass) -> UShortSerializer + UInt::class.java.isAssignableFrom(rawClass) -> UIntSerializer + ULong::class.java.isAssignableFrom(rawClass) -> ULongSerializer + // The priority of Unboxing needs to be lowered so as not to break the serialization of Unsigned Integers. + rawClass.isUnboxableValueClass() -> ValueClassSerializer.from(rawClass) + else -> null + } } } From a51e1a2b9d21af619a85ef728f980bcc4d75943b Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 2 Jan 2022 16:19:29 +0900 Subject: [PATCH 6/8] add test cases --- .../module/kotlin/test/github/GitHub530.kt | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt index 831ad2de3..a4106b68e 100644 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt @@ -45,7 +45,7 @@ class GitHub530 { ) @Test - fun test() { + fun inProperty() { val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() assertEquals( @@ -80,4 +80,24 @@ class GitHub530 { ) ) } + + @Test + fun inCollection() { + val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() + + assertEquals( + "[ 0, 1, \"Baz(value=2)\", \"Qux(value=3)\", \"Quux(value=4)\" ]", + writer.writeValueAsString(listOf(Foo(0), Bar(1), Baz(2), Qux(3), Quux(4))) + ) + } + + @Test + fun inArray() { + val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() + + assertEquals( + "[ 0, 1, \"Baz(value=2)\", \"Qux(value=3)\", \"Quux(value=4)\" ]", + writer.writeValueAsString(arrayOf(Foo(0), Bar(1), Baz(2), Qux(3), Quux(4))) + ) + } } From c0ab03802a22a6fb7b078d1d0db89da006fd4824 Mon Sep 17 00:00:00 2001 From: Drew Stephens Date: Mon, 3 Jan 2022 06:26:49 -0500 Subject: [PATCH 7/8] Split out separate tests --- .../module/kotlin/test/github/GitHub530.kt | 249 +++++++++++++----- 1 file changed, 190 insertions(+), 59 deletions(-) diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt index a4106b68e..99139ea42 100644 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub530.kt @@ -2,102 +2,233 @@ package com.fasterxml.jackson.module.kotlin.test.github import com.fasterxml.jackson.annotation.JsonValue import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder -import org.junit.Test import kotlin.test.assertEquals +import org.junit.Test class GitHub530 { // At the moment, the output is the same with or without `JsonValue`, // but this pattern is included in the test case in case the option to default to a serialization method that // does not `unbox` is introduced in the future. - @JvmInline value class Foo(@get:JsonValue val value: Int) - @JvmInline value class Bar(@JvmField @field:JsonValue val value: Int) + @JvmInline + value class ValueParamGetterAnnotated(@get:JsonValue val value: Int) - @JvmInline value class Baz(val value: Int) { - @get:JsonValue val jsonValue: String get() = this.toString() + @JvmInline + value class ValueParamFieldAnnotated(@JvmField @field:JsonValue val value: Int) + + @JvmInline + value class PropertyWithOverriddenGetter(val value: Int) { + @get:JsonValue + val jsonValue: String + get() = this.toString() } - @JvmInline value class Qux(val value: Int) { - @JsonValue fun getJsonValue(): String = this.toString() + + @JvmInline + value class DirectlyOverriddenGetter(val value: Int) { + @JsonValue + fun getJsonValue(): String = this.toString() } - interface JsonValueGetter { @get:JsonValue val jsonValue: String get() = this.toString() } - @JvmInline value class Quux(val value: Int): JsonValueGetter - @JvmInline value class Corge(val value: Int): JsonValueGetter + interface JsonValueGetter { + @get:JsonValue + val jsonValue: String + get() = this.toString() + } + + @JvmInline + value class JsonValueGetterImplementation(val value: Int) : JsonValueGetter + + private val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() - @JvmInline value class Grault(val value: Int) { - @get:JsonValue val jsonValue: String get() = this.toString() + @Test + fun valueParamGetterAnnotated() { + data class Data( + val nonNull: ValueParamGetterAnnotated, + val nullable: ValueParamGetterAnnotated? + ) + + assertEquals( + """ + { + "nonNull" : 0, + "nullable" : 1 + } + """.trimIndent(), + writer.writeValueAsString( + Data( + ValueParamGetterAnnotated(0), + ValueParamGetterAnnotated(1) + ) + ) + ) } - data class Data( - val foo1: Foo, - val foo2: Foo?, - val bar1: Bar, - val bar2: Bar?, - val baz1: Baz, - val baz2: Baz?, - val qux1: Qux, - val qux2: Qux?, - val quux1: Quux, - val quux2: Quux?, - val corge1: JsonValueGetter, - val corge2: JsonValueGetter?, - val grault1: T, - val grault2: T? - ) + @Test + fun valueParamFieldAnnoated() { + data class Data( + val nonNull: ValueParamFieldAnnotated, + val nullable: ValueParamFieldAnnotated? + ) + + assertEquals( + """ + { + "nonNull" : 0, + "nullable" : 1 + } + """.trimIndent(), + writer.writeValueAsString( + Data( + ValueParamFieldAnnotated(0), + ValueParamFieldAnnotated(1) + ) + ) + ) + } @Test - fun inProperty() { - val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() + fun propertyWithOverriddenGetter() { + data class Data( + val nonNull: PropertyWithOverriddenGetter, + val nullable: PropertyWithOverriddenGetter? + ) assertEquals( """ { - "foo1" : 0, - "foo2" : 1, - "bar1" : 2, - "bar2" : 3, - "baz1" : "Baz(value=4)", - "baz2" : "Baz(value=5)", - "qux1" : "Qux(value=6)", - "qux2" : "Qux(value=7)", - "quux1" : "Quux(value=8)", - "quux2" : "Quux(value=9)", - "corge1" : "Corge(value=10)", - "corge2" : "Corge(value=11)", - "grault1" : "Grault(value=12)", - "grault2" : "Grault(value=13)" + "nonNull" : "PropertyWithOverriddenGetter(value=0)", + "nullable" : "PropertyWithOverriddenGetter(value=1)" } """.trimIndent(), writer.writeValueAsString( Data( - Foo(0), Foo(1), - Bar(2), Bar(3), - Baz(4), Baz(5), - Qux(6), Qux(7), - Quux(8), Quux(9), - Corge(10), Corge(11), - Grault(12), Grault(13) + PropertyWithOverriddenGetter(0), + PropertyWithOverriddenGetter(1) ) ) ) } @Test - fun inCollection() { - val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() + fun directlyOverriddenGetter() { + data class Data( + val nonNull: DirectlyOverriddenGetter, + val nullable: DirectlyOverriddenGetter? + ) assertEquals( - "[ 0, 1, \"Baz(value=2)\", \"Qux(value=3)\", \"Quux(value=4)\" ]", - writer.writeValueAsString(listOf(Foo(0), Bar(1), Baz(2), Qux(3), Quux(4))) + """ + { + "nonNull" : "DirectlyOverriddenGetter(value=0)", + "nullable" : "DirectlyOverriddenGetter(value=1)" + } + """.trimIndent(), + writer.writeValueAsString( + Data( + DirectlyOverriddenGetter(0), + DirectlyOverriddenGetter(1) + ) + ) ) } @Test - fun inArray() { - val writer = jacksonMapperBuilder().build().writerWithDefaultPrettyPrinter() + fun propertyWithOverriddenGetterAsParameterizedType() { + data class Data( + val nonNull: T, + val nullable: T? + ) assertEquals( - "[ 0, 1, \"Baz(value=2)\", \"Qux(value=3)\", \"Quux(value=4)\" ]", - writer.writeValueAsString(arrayOf(Foo(0), Bar(1), Baz(2), Qux(3), Quux(4))) + """ + { + "nonNull" : "PropertyWithOverriddenGetter(value=0)", + "nullable" : "PropertyWithOverriddenGetter(value=1)" + } + """.trimIndent(), + writer.writeValueAsString( + Data( + PropertyWithOverriddenGetter(0), + PropertyWithOverriddenGetter(1) + ) + ) + ) + } + + @Test + fun jsonValueGetterImplementationAsConcreteType() { + data class Data( + val nonNull: JsonValueGetterImplementation, + val nullable: JsonValueGetterImplementation? + ) + + assertEquals( + """ + { + "nonNull" : "JsonValueGetterImplementation(value=0)", + "nullable" : "JsonValueGetterImplementation(value=1)" + } + """.trimIndent(), + writer.writeValueAsString( + Data( + JsonValueGetterImplementation(0), + JsonValueGetterImplementation(1) + ) + ) + ) + } + + @Test + fun jsonValueGetterImplementationAsGenericType() { + data class Data( + val nonNull: JsonValueGetter, + val nullable: JsonValueGetter? + ) + + assertEquals( + """ + { + "nonNull" : "JsonValueGetterImplementation(value=0)", + "nullable" : "JsonValueGetterImplementation(value=1)" + } + """.trimIndent(), + writer.writeValueAsString( + Data( + JsonValueGetterImplementation(0), + JsonValueGetterImplementation(1) + ) + ) + ) + } + + @Test + fun inCollection() { + assertEquals( + "[ 0, 1, \"PropertyWithOverriddenGetter(value=2)\", \"DirectlyOverriddenGetter(value=3)\", \"JsonValueGetterImplementation(value=4)\" ]", + writer.writeValueAsString( + listOf( + ValueParamGetterAnnotated(0), + ValueParamFieldAnnotated(1), + PropertyWithOverriddenGetter(2), + DirectlyOverriddenGetter(3), + JsonValueGetterImplementation(4) + ) + ) + ) + } + + @Test + fun inArray() { + assertEquals( + "[ 0, 1, \"PropertyWithOverriddenGetter(value=2)\", \"DirectlyOverriddenGetter(value=3)\", \"JsonValueGetterImplementation(value=4)\" ]", + writer.writeValueAsString( + arrayOf( + ValueParamGetterAnnotated(0), + ValueParamFieldAnnotated(1), + PropertyWithOverriddenGetter(2), + DirectlyOverriddenGetter(3), + JsonValueGetterImplementation(4) + ) + ) ) } } From cc6c5368a0f5fc8a2456a997325e178b8beeb8f5 Mon Sep 17 00:00:00 2001 From: Drew Stephens Date: Mon, 3 Jan 2022 10:46:24 -0500 Subject: [PATCH 8/8] Update japicmp excludes --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index 91dbace1b..dd4b2f897 100644 --- a/pom.xml +++ b/pom.xml @@ -208,6 +208,13 @@ TODO Remove after release of 2.14 and update the oldVersion above to 2.14. --> com.fasterxml.jackson.module.kotlin.ValueClassBoxSerializer + com.fasterxml.jackson.module.kotlin.ValueClassSerializer$StaticJsonValue + com.fasterxml.jackson.module.kotlin.ValueClassSerializer$Unbox + com.fasterxml.jackson.module.kotlin.ValueClassStaticJsonValueSerializer + com.fasterxml.jackson.module.kotlin.ValueClassUnboxSerializer.serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider) + com.fasterxml.jackson.databind.jsonschema.SchemaAware[com.fasterxml.jackson.databind.jsonschema.SchemaAware] + com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable[com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable]:INTERFACE_REMOVED, java.io.Serializable[java.io.Serializable] + com.fasterxml.jackson.module.kotlin.ValueClassUnboxSerializer