Skip to content

Commit 01a1e81

Browse files
committed
Fixed a regression related to deserializing value classes with private constructor
1 parent e75575a commit 01a1e81

File tree

6 files changed

+24
-18
lines changed

6 files changed

+24
-18
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ internal class IntValueClassUnboxConverter<T : Any>(
165165
unboxMethod: Method,
166166
) : ValueClassUnboxConverter<T, Int>() {
167167
override val unboxedType: Type get() = Int::class.java
168-
override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_INT_METHOD_TYPE)
168+
override val unboxHandle: MethodHandle = unreflectAsTypeWithAccessibilityModification(unboxMethod, ANY_TO_INT_METHOD_TYPE)
169169

170170
override fun convert(value: T): Int = unboxHandle.invokeExact(value) as Int
171171
}
@@ -175,7 +175,7 @@ internal class LongValueClassUnboxConverter<T : Any>(
175175
unboxMethod: Method,
176176
) : ValueClassUnboxConverter<T, Long>() {
177177
override val unboxedType: Type get() = Long::class.java
178-
override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_LONG_METHOD_TYPE)
178+
override val unboxHandle: MethodHandle = unreflectAsTypeWithAccessibilityModification(unboxMethod, ANY_TO_LONG_METHOD_TYPE)
179179

180180
override fun convert(value: T): Long = unboxHandle.invokeExact(value) as Long
181181
}
@@ -185,7 +185,7 @@ internal class StringValueClassUnboxConverter<T : Any>(
185185
unboxMethod: Method,
186186
) : ValueClassUnboxConverter<T, String?>() {
187187
override val unboxedType: Type get() = String::class.java
188-
override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_STRING_METHOD_TYPE)
188+
override val unboxHandle: MethodHandle = unreflectAsTypeWithAccessibilityModification(unboxMethod, ANY_TO_STRING_METHOD_TYPE)
189189

190190
override fun convert(value: T): String? = unboxHandle.invokeExact(value) as String?
191191
}
@@ -195,7 +195,7 @@ internal class JavaUuidValueClassUnboxConverter<T : Any>(
195195
unboxMethod: Method,
196196
) : ValueClassUnboxConverter<T, UUID?>() {
197197
override val unboxedType: Type get() = UUID::class.java
198-
override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_JAVA_UUID_METHOD_TYPE)
198+
override val unboxHandle: MethodHandle = unreflectAsTypeWithAccessibilityModification(unboxMethod, ANY_TO_JAVA_UUID_METHOD_TYPE)
199199

200200
override fun convert(value: T): UUID? = unboxHandle.invokeExact(value) as UUID?
201201
}
@@ -205,7 +205,7 @@ internal class GenericValueClassUnboxConverter<T : Any>(
205205
override val unboxedType: Type,
206206
unboxMethod: Method,
207207
) : ValueClassUnboxConverter<T, Any?>() {
208-
override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_ANY_METHOD_TYPE)
208+
override val unboxHandle: MethodHandle = unreflectAsTypeWithAccessibilityModification(unboxMethod, ANY_TO_ANY_METHOD_TYPE)
209209

210210
override fun convert(value: T): Any? = unboxHandle.invokeExact(value)
211211
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.fasterxml.jackson.module.kotlin
22

33
import com.fasterxml.jackson.annotation.JsonCreator
44
import com.fasterxml.jackson.databind.JsonMappingException
5+
import com.fasterxml.jackson.databind.util.ClassUtil
56
import java.lang.invoke.MethodHandle
67
import java.lang.invoke.MethodHandles
78
import java.lang.invoke.MethodType
@@ -61,5 +62,10 @@ internal val LONG_TO_ANY_METHOD_TYPE by lazy {MethodType.methodType(Any::class.j
6162
internal val STRING_TO_ANY_METHOD_TYPE by lazy {MethodType.methodType(Any::class.java, String::class.java) }
6263
internal val JAVA_UUID_TO_ANY_METHOD_TYPE by lazy {MethodType.methodType(Any::class.java, UUID::class.java) }
6364

64-
internal fun unreflect(method: Method): MethodHandle = MethodHandles.lookup().unreflect(method)
65-
internal fun unreflectAsType(method: Method, type: MethodType): MethodHandle = unreflect(method).asType(type)
65+
internal fun unreflectWithAccessibilityModification(method: Method): MethodHandle = MethodHandles.lookup().unreflect(
66+
method.apply { ClassUtil.checkAndFixAccess(this, false) },
67+
)
68+
internal fun unreflectAsTypeWithAccessibilityModification(
69+
method: Method,
70+
type: MethodType,
71+
): MethodHandle = unreflectWithAccessibilityModification(method).asType(type)

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ internal sealed class NoConversionCreatorBoxDeserializer<S, D : Any>(
109109
) : WrapsNullableValueClassDeserializer<D>(converter.boxedClass) {
110110
protected abstract val inputType: Class<*>
111111
protected val handle: MethodHandle = MethodHandles
112-
.filterReturnValue(unreflect(creator), converter.boxHandle)
112+
.filterReturnValue(unreflectWithAccessibilityModification(creator), converter.boxHandle)
113113

114114
// Since the input to handle must be strict, invoke should be implemented in each class
115115
protected abstract fun invokeExact(value: S): D
@@ -190,7 +190,7 @@ internal class HasConversionCreatorWrapsSpecifiedBoxDeserializer<S, D : Any>(
190190
private val handle: MethodHandle
191191

192192
init {
193-
val unreflect = unreflect(creator).run {
193+
val unreflect = unreflectWithAccessibilityModification(creator).run {
194194
asType(type().changeParameterType(0, Any::class.java))
195195
}
196196
handle = MethodHandles.filterReturnValue(unreflect, converter.boxHandle)
@@ -222,7 +222,7 @@ internal class WrapsAnyValueClassBoxDeserializer<S, D : Any>(
222222
private val handle: MethodHandle
223223

224224
init {
225-
val unreflect = unreflectAsType(creator, ANY_TO_ANY_METHOD_TYPE)
225+
val unreflect = unreflectAsTypeWithAccessibilityModification(creator, ANY_TO_ANY_METHOD_TYPE)
226226
handle = MethodHandles.filterReturnValue(unreflect, converter.boxHandle)
227227
}
228228

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ internal sealed class ValueClassKeyDeserializer<S, D : Any>(
112112
// Currently, only the primary constructor can be the creator of a key, so for specified types,
113113
// the return type of the primary constructor and the input type of the box function are exactly the same.
114114
// Therefore, performance is improved by omitting the asType call.
115-
unreflect(creator),
115+
unreflectWithAccessibilityModification(creator),
116116
)
117117

118118
internal class WrapsInt<D : Any>(
@@ -160,7 +160,7 @@ internal sealed class ValueClassKeyDeserializer<S, D : Any>(
160160
creator: Method,
161161
) : ValueClassKeyDeserializer<S, D>(
162162
converter,
163-
unreflectAsType(creator, ANY_TO_ANY_METHOD_TYPE),
163+
unreflectAsTypeWithAccessibilityModification(creator, ANY_TO_ANY_METHOD_TYPE),
164164
) {
165165
override val unboxedClass: Class<*> = creator.returnType
166166

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal sealed class ValueClassStaticJsonKeySerializer<T : Any>(
3737
methodType: MethodType,
3838
) : StdSerializer<T>(converter.valueClass) {
3939
private val keyType: Class<*> = staticJsonValueGetter.returnType
40-
private val handle: MethodHandle = unreflectAsType(staticJsonValueGetter, methodType).let {
40+
private val handle: MethodHandle = unreflectAsTypeWithAccessibilityModification(staticJsonValueGetter, methodType).let {
4141
MethodHandles.filterReturnValue(converter.unboxHandle, it)
4242
}
4343

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,39 +82,39 @@ internal sealed class ValueClassStaticJsonValueSerializer<T : Any>(
8282
staticJsonValueGetter: Method,
8383
) : ValueClassStaticJsonValueSerializer<T>(
8484
converter,
85-
unreflectAsType(staticJsonValueGetter, INT_TO_ANY_METHOD_TYPE),
85+
unreflectAsTypeWithAccessibilityModification(staticJsonValueGetter, INT_TO_ANY_METHOD_TYPE),
8686
)
8787

8888
internal class WrapsLong<T : Any>(
8989
converter: LongValueClassUnboxConverter<T>,
9090
staticJsonValueGetter: Method,
9191
) : ValueClassStaticJsonValueSerializer<T>(
9292
converter,
93-
unreflectAsType(staticJsonValueGetter, LONG_TO_ANY_METHOD_TYPE),
93+
unreflectAsTypeWithAccessibilityModification(staticJsonValueGetter, LONG_TO_ANY_METHOD_TYPE),
9494
)
9595

9696
internal class WrapsString<T : Any>(
9797
converter: StringValueClassUnboxConverter<T>,
9898
staticJsonValueGetter: Method,
9999
) : ValueClassStaticJsonValueSerializer<T>(
100100
converter,
101-
unreflectAsType(staticJsonValueGetter, STRING_TO_ANY_METHOD_TYPE),
101+
unreflectAsTypeWithAccessibilityModification(staticJsonValueGetter, STRING_TO_ANY_METHOD_TYPE),
102102
)
103103

104104
internal class WrapsJavaUuid<T : Any>(
105105
converter: JavaUuidValueClassUnboxConverter<T>,
106106
staticJsonValueGetter: Method,
107107
) : ValueClassStaticJsonValueSerializer<T>(
108108
converter,
109-
unreflectAsType(staticJsonValueGetter, JAVA_UUID_TO_ANY_METHOD_TYPE),
109+
unreflectAsTypeWithAccessibilityModification(staticJsonValueGetter, JAVA_UUID_TO_ANY_METHOD_TYPE),
110110
)
111111

112112
internal class WrapsAny<T : Any>(
113113
converter: GenericValueClassUnboxConverter<T>,
114114
staticJsonValueGetter: Method,
115115
) : ValueClassStaticJsonValueSerializer<T>(
116116
converter,
117-
unreflectAsType(staticJsonValueGetter, ANY_TO_ANY_METHOD_TYPE),
117+
unreflectAsTypeWithAccessibilityModification(staticJsonValueGetter, ANY_TO_ANY_METHOD_TYPE),
118118
)
119119

120120
companion object {

0 commit comments

Comments
 (0)