Skip to content

Commit fe712e9

Browse files
authored
Merge pull request #155 from ProjectMapK/fix/cache
Cache efficiency for boxed return types
2 parents 248d372 + 9df7daa commit fe712e9

File tree

2 files changed

+17
-15
lines changed

2 files changed

+17
-15
lines changed

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ReflectionCache.kt

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.github.projectmapk.jackson.module.kogera
33
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod
44
import com.fasterxml.jackson.databind.util.LRUMap
55
import java.io.Serializable
6+
import java.lang.reflect.Method
67
import java.util.Optional
78

89
internal class ReflectionCache(reflectionCacheSize: Int) : Serializable {
@@ -16,7 +17,7 @@ internal class ReflectionCache(reflectionCacheSize: Int) : Serializable {
1617
private val classCache = LRUMap<Class<*>, JmClass>(reflectionCacheSize, reflectionCacheSize)
1718

1819
// Initial size is 0 because the value class is not always used
19-
private val valueClassReturnTypeCache: LRUMap<AnnotatedMethod, Optional<Class<*>>> =
20+
private val valueClassReturnTypeCache: LRUMap<Method, Optional<Class<*>>> =
2021
LRUMap(0, reflectionCacheSize)
2122

2223
// TODO: Consider whether the cache size should be reduced more,
@@ -46,28 +47,29 @@ internal class ReflectionCache(reflectionCacheSize: Int) : Serializable {
4647
}
4748
}
4849

49-
private fun AnnotatedMethod.getValueClassReturnType(): Class<*>? {
50-
val getter = this.member.apply {
51-
// If the return value of the getter is a value class,
52-
// it will be serialized properly without doing anything.
53-
// TODO: Verify the case where a value class encompasses another value class.
54-
if (this.returnType.isUnboxableValueClass()) return null
55-
}
56-
val kotlinProperty = getJmClass(getter.declaringClass)?.findPropertyByGetter(getter)
50+
private fun Method.getValueClassReturnType(): Class<*>? {
51+
val kotlinProperty = getJmClass(declaringClass)?.findPropertyByGetter(this)
5752

5853
// Since there was no way to directly determine whether returnType is a value class or not,
5954
// Class is restored and processed.
6055
return kotlinProperty?.returnType?.reconstructClassOrNull()?.takeIf { it.isUnboxableValueClass() }
6156
}
6257

63-
fun findValueClassReturnType(getter: AnnotatedMethod): Class<*>? {
64-
val optional = valueClassReturnTypeCache.get(getter)
58+
// Return boxed type on Kotlin for unboxed getters
59+
fun findBoxedReturnType(getter: AnnotatedMethod): Class<*>? {
60+
val method = getter.member
61+
val optional = valueClassReturnTypeCache.get(method)
6562

6663
return if (optional != null) {
6764
optional
6865
} else {
69-
val value = Optional.ofNullable(getter.getValueClassReturnType())
70-
(valueClassReturnTypeCache.putIfAbsent(getter, value) ?: value)
66+
// If the return value of the getter is a value class,
67+
// it will be serialized properly without doing anything.
68+
// TODO: Verify the case where a value class encompasses another value class.
69+
if (method.returnType.isUnboxableValueClass()) return null
70+
71+
val value = Optional.ofNullable(method.getValueClassReturnType())
72+
(valueClassReturnTypeCache.putIfAbsent(method, value) ?: value)
7173
}.orElse(null)
7274
}
7375

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/annotation_introspector/KotlinFallbackAnnotationIntrospector.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ internal class KotlinFallbackAnnotationIntrospector(
7676

7777
override fun findSerializationConverter(a: Annotated): Converter<*, *>? = when (a) {
7878
// Find a converter to handle the case where the getter returns an unboxed value from the value class.
79-
is AnnotatedMethod -> cache.findValueClassReturnType(a)?.let {
79+
is AnnotatedMethod -> cache.findBoxedReturnType(a)?.let {
8080
if (useJavaDurationConversion && it == KotlinDuration::class.java) {
8181
if (a.rawReturnType == KotlinDuration::class.java) {
8282
KotlinToJavaDurationConverter
@@ -110,7 +110,7 @@ internal class KotlinFallbackAnnotationIntrospector(
110110
// Perform proper serialization even if the value wrapped by the value class is null.
111111
// If value is a non-null object type, it must not be reboxing.
112112
override fun findNullSerializer(am: Annotated): JsonSerializer<*>? = (am as? AnnotatedMethod)?.let { _ ->
113-
cache.findValueClassReturnType(am)?.let {
113+
cache.findBoxedReturnType(am)?.let {
114114
if (it.requireRebox()) cache.getValueClassBoxConverter(am.rawReturnType, it).delegatingSerializer else null
115115
}
116116
}

0 commit comments

Comments
 (0)