Skip to content

Commit 756d544

Browse files
committed
fix for boxed cases
1 parent 02fea55 commit 756d544

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,43 @@ object ULongSerializer : StdSerializer<ULong>(ULong::class.java) {
4949
private fun Class<*>.getStaticJsonValueGetter(): Method? = this.declaredMethods
5050
.find { method -> Modifier.isStatic(method.modifiers) && method.annotations.any { it is JsonValue } }
5151

52-
object ValueClassUnboxSerializer : StdSerializer<Any>(Any::class.java) {
53-
override fun serialize(value: Any, gen: JsonGenerator, provider: SerializerProvider) {
54-
val unboxed = value::class.java.getMethod("unbox-impl").invoke(value)
52+
internal sealed class ValueClassSerializer<T : Any>(t: Class<T>) : StdSerializer<T>(t) {
53+
object Unbox : ValueClassSerializer<Any>(Any::class.java) {
54+
override fun serialize(value: Any, gen: JsonGenerator, provider: SerializerProvider) {
55+
val unboxed = value::class.java.getMethod("unbox-impl").invoke(value)
5556

56-
if (unboxed == null) {
57-
provider.findNullValueSerializer(null).serialize(unboxed, gen, provider)
58-
return
57+
if (unboxed == null) {
58+
provider.findNullValueSerializer(null).serialize(unboxed, gen, provider)
59+
return
60+
}
61+
62+
provider.findValueSerializer(unboxed::class.java).serialize(unboxed, gen, provider)
63+
}
64+
}
65+
66+
class StaticJsonValue<T : Any>(
67+
t: Class<T>, private val staticJsonValueGetter: Method
68+
) : ValueClassSerializer<T>(t) {
69+
private val unboxMethod: Method = t.getMethod("unbox-impl")
70+
71+
override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) {
72+
val unboxed = unboxMethod.invoke(value)
73+
// As shown in the processing of the factory function, jsonValueGetter is always a static method.
74+
val jsonValue: Any? = staticJsonValueGetter.invoke(null, unboxed)
75+
jsonValue
76+
?.let { provider.findValueSerializer(it::class.java).serialize(it, gen, provider) }
77+
?: provider.findNullValueSerializer(null).serialize(null, gen, provider)
5978
}
79+
}
6080

61-
provider.findValueSerializer(unboxed::class.java).serialize(unboxed, gen, provider)
81+
companion object {
82+
// `t` must be UnboxableValueClass.
83+
// If create a function with a JsonValue in the value class,
84+
// it will be compiled as a static method (= cannot be processed properly by Jackson),
85+
// so use a ValueClassSerializer.StaticJsonValue to handle this.
86+
fun from(t: Class<*>): ValueClassSerializer<*> = t.getStaticJsonValueGetter()
87+
?.let { StaticJsonValue(t, it) }
88+
?: Unbox
6289
}
6390
}
6491

@@ -74,7 +101,7 @@ internal class KotlinSerializers : Serializers.Base() {
74101
UInt::class.java.isAssignableFrom(type.rawClass) -> UIntSerializer
75102
ULong::class.java.isAssignableFrom(type.rawClass) -> ULongSerializer
76103
// The priority of Unboxing needs to be lowered so as not to break the serialization of Unsigned Integers.
77-
type.rawClass.isUnboxableValueClass() -> ValueClassUnboxSerializer
104+
type.rawClass.isUnboxableValueClass() -> ValueClassSerializer.from(type.rawClass)
78105
else -> null
79106
}
80107
}

0 commit comments

Comments
 (0)