Skip to content

Commit a10665c

Browse files
authored
Merge pull request #227 from ProjectMapK/develop
Release 2024-03-30 06:53:34 +0000
2 parents c682e69 + 06d5964 commit a10665c

File tree

15 files changed

+51
-47
lines changed

15 files changed

+51
-47
lines changed

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ First, by implementing the equivalent of https://github.com/FasterXML/jackson-mo
2323
The cache has also been reorganized based on [benchmark results](https://github.com/ProjectMapK/kogera-benchmark) to achieve smaller memory consumption.
2424
The performance degradation when the `strictNullChecks` option is enabled is also [greatly reduced](https://github.com/ProjectMapK/jackson-module-kogera/pull/44).
2525

26-
The next main feature is `value class` support.
27-
The `jackson-module-kogera` supports many use cases for `value class`, including deserialization.
28-
See [here](./docs/AboutValueClassSupport.md) for basic policies and notes on handling `value class`.
29-
3026
[Here](./docs/FixedIssues.md) is a list of issues that are not resolved in `jackson-module-kotlin` but are or will be resolved in `kogera`.
3127

3228
## About intentional destructive changes

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ val jacksonVersion = libs.versions.jackson.get()
1616
val generatedSrcPath = "${layout.buildDirectory.get()}/generated/kotlin"
1717

1818
group = groupStr
19-
version = "${jacksonVersion}-beta11"
19+
version = "${jacksonVersion}-beta12"
2020

2121
repositories {
2222
mavenCentral()

docs/FixedIssues.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
A list of issues that have not been resolved in `jackson-module-kotlin`, but have been or will be resolved in `kogera`.
22

33
## Fixed
4-
- [Support for inline classes · Issue \#199](https://github.com/FasterXML/jackson-module-kotlin/issues/199)
54
- [Getting MismatchedInputException instead of MissingKotlinParameterException · Issue \#234](https://github.com/FasterXML/jackson-module-kotlin/issues/234)
65
- [Private getter with different return type hides property · Issue \#341](https://github.com/FasterXML/jackson-module-kotlin/issues/341)
76
- [Remove \`kotlin\-reflect\` and replace it with \`kotlinx\-metadata\-jvm\` · Issue \#450](https://github.com/FasterXML/jackson-module-kotlin/issues/450)
8-
- [Supports deserialization of \`value class\` \(\`inline class\`\)\. · Issue \#650](https://github.com/FasterXML/jackson-module-kotlin/issues/650)
97
- [Annotation given to constructor parameters containing \`value class\` as argument does not work · Issue \#651](https://github.com/FasterXML/jackson-module-kotlin/issues/651)
108
- [How to deserialize a kotlin\.ranges\.ClosedRange<T> with Jackson · Issue \#663](https://github.com/FasterXML/jackson-module-kotlin/issues/663)
119
- [There are cases where \`isRequired\` specifications are not properly merged\. · Issue \#668](https://github.com/FasterXML/jackson-module-kotlin/issues/668)
1210

1311
## Want to fix
1412
- [There are some problems with KNAI\.hasCreatorAnnotation · Issue \#547](https://github.com/FasterXML/jackson-module-kotlin/issues/547)
15-
- [This module shouldn't bring kotlin\-reflect 1\.5 as a transitive dependency · Issue \#566](https://github.com/FasterXML/jackson-module-kotlin/issues/566)

docs/KogeraSpecificImplementations.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,3 @@ I will consider making the classes public again when we receive requests for the
2525
## Remove old options and `deprecated` code
2626
Because `jackson-module-kotlin` is a framework with a long history, some old code and options remain.
2727
In `kogera`, those options have been removed.
28-
29-
# Value class support
30-
The `jackson-module-kogera` supports many use cases of `value class` (`inline class`).
31-
This is summarized [here](./AboutValueClassSupport.md).

gradle/libs.versions.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[versions]
22
kotlin = "1.8.22" # Mainly for CI, it can be rewritten by environment variable.
3-
jackson = "2.16.1"
3+
jackson = "2.17.0"
44

55
# test libs
6-
junit = "5.10.1"
6+
junit = "5.10.2"
77

88
[libraries]
99
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib" }
@@ -16,7 +16,7 @@ kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect" }
1616
junit-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
1717
junit-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
1818
junit-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
19-
mockk = "io.mockk:mockk:1.13.7"
19+
mockk = "io.mockk:mockk:1.13.10"
2020
jackson-xml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-xml", version.ref = "jackson" }
2121
jackson-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" }
2222

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ internal object ClosedRangeResolver : SimpleAbstractTypeResolver() {
5555
}
5656

5757
fun findClosedFloatingPointRangeRef(contentType: Class<*>): Class<*>? = when (contentType) {
58-
Double::class.javaPrimitiveType, Double::class.javaObjectType -> closedDoubleRangeRef
59-
Float::class.javaPrimitiveType, Float::class.javaObjectType -> closedFloatRangeRef
58+
Double::class.java, Double::class.javaObjectType -> closedDoubleRangeRef
59+
Float::class.java, Float::class.javaObjectType -> closedFloatRangeRef
6060
else -> null
6161
}
6262

@@ -67,7 +67,7 @@ internal object ClosedRangeResolver : SimpleAbstractTypeResolver() {
6767
override fun findTypeMapping(config: DeserializationConfig, type: JavaType): JavaType? {
6868
val rawClass = type.rawClass
6969

70-
return if (rawClass == ClosedRange::class.java || rawClass == ClosedFloatingPointRange::class.java) {
70+
return if (rawClass == ClosedRange::class.java || rawClass == CLOSED_FLOATING_POINT_RANGE_CLASS) {
7171
type.bindings.typeParameters.firstOrNull()
7272
?.let { typeParam ->
7373
findClosedFloatingPointRangeRef(typeParam.rawClass)?.let {

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

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.github.projectmapk.jackson.module.kogera
22

33
import com.fasterxml.jackson.annotation.JsonCreator
4+
import com.fasterxml.jackson.annotation.JsonProperty
5+
import io.github.projectmapk.jackson.module.kogera.annotation.JsonKUnbox
46
import kotlinx.metadata.KmClass
57
import kotlinx.metadata.KmClassifier
68
import kotlinx.metadata.KmType
@@ -14,25 +16,25 @@ import java.lang.reflect.Method
1416
internal typealias JavaDuration = java.time.Duration
1517
internal typealias KotlinDuration = kotlin.time.Duration
1618

17-
internal fun Class<*>.toKmClass(): KmClass? = getAnnotation(Metadata::class.java)?.let {
19+
internal fun Class<*>.toKmClass(): KmClass? = getAnnotation(METADATA_CLASS)?.let {
1820
(KotlinClassMetadata.readStrict(it) as KotlinClassMetadata.Class).kmClass
1921
}
2022

21-
internal fun Class<*>.isUnboxableValueClass() = this.isAnnotationPresent(JvmInline::class.java)
23+
internal fun Class<*>.isUnboxableValueClass() = this.isAnnotationPresent(JVM_INLINE_CLASS)
2224

2325
// JmClass must be value class.
2426
internal fun JmClass.wrapsNullValueClass() = inlineClassUnderlyingType!!.isNullable
2527

2628
private val primitiveClassToDesc = mapOf(
27-
Byte::class.javaPrimitiveType to 'B',
28-
Char::class.javaPrimitiveType to 'C',
29-
Double::class.javaPrimitiveType to 'D',
30-
Float::class.javaPrimitiveType to 'F',
31-
Int::class.javaPrimitiveType to 'I',
32-
Long::class.javaPrimitiveType to 'J',
33-
Short::class.javaPrimitiveType to 'S',
34-
Boolean::class.javaPrimitiveType to 'Z',
35-
Void::class.javaPrimitiveType to 'V'
29+
Byte::class.java to 'B',
30+
Char::class.java to 'C',
31+
Double::class.java to 'D',
32+
Float::class.java to 'F',
33+
Int::class.java to 'I',
34+
Long::class.java to 'J',
35+
Short::class.java to 'S',
36+
Boolean::class.java to 'Z',
37+
Void.TYPE to 'V'
3638
)
3739

3840
// -> this.name.replace(".", "/")
@@ -88,6 +90,19 @@ internal fun String.reconstructClass(): Class<*> {
8890
internal fun KmType.reconstructClassOrNull(): Class<*>? = (classifier as? KmClassifier.Class)
8991
?.let { kotlin.runCatching { it.name.reconstructClass() }.getOrNull() }
9092

91-
internal fun AnnotatedElement.hasCreatorAnnotation(): Boolean = getAnnotation(JsonCreator::class.java)
93+
internal fun AnnotatedElement.hasCreatorAnnotation(): Boolean = getAnnotation(JSON_CREATOR_CLASS)
9294
?.let { it.mode != JsonCreator.Mode.DISABLED }
9395
?: false
96+
97+
// Instantiating Java Class as a static property is expected to improve first-time execution performance.
98+
// However, maybe this improvement is limited to Java Classes that are not used to initialize static content.
99+
// Also, for classes that are read at the time of initialization of static content or module initialization,
100+
// optimization seems unnecessary because caching is effective.
101+
internal val METADATA_CLASS = Metadata::class.java
102+
internal val JVM_INLINE_CLASS = JvmInline::class.java
103+
internal val JSON_CREATOR_CLASS = JsonCreator::class.java
104+
internal val JSON_PROPERTY_CLASS = JsonProperty::class.java
105+
internal val JSON_K_UNBOX_CLASS = JsonKUnbox::class.java
106+
internal val KOTLIN_DURATION_CLASS = KotlinDuration::class.java
107+
internal val CLOSED_FLOATING_POINT_RANGE_CLASS = ClosedFloatingPointRange::class.java
108+
internal val ANY_CLASS = Any::class.java

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ internal object KotlinClassIntrospector : BasicClassIntrospector() {
5050
?: run {
5151
val coll = collectProperties(config, type, r, true)
5252

53-
if (type.rawClass.isAnnotationPresent(Metadata::class.java)) {
53+
if (type.rawClass.isAnnotationPresent(METADATA_CLASS)) {
5454
KotlinBeanDescription(coll)
5555
} else {
5656
BasicBeanDescription.forDeserialization(coll)
@@ -71,7 +71,7 @@ internal object KotlinClassIntrospector : BasicClassIntrospector() {
7171
?: run {
7272
val coll = collectProperties(config, type, r, false)
7373

74-
if (type.rawClass.isAnnotationPresent(Metadata::class.java)) {
74+
if (type.rawClass.isAnnotationPresent(METADATA_CLASS)) {
7575
KotlinBeanDescription(coll)
7676
} else {
7777
BasicBeanDescription.forDeserialization(coll)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ internal class ReflectionCache(initialCacheSize: Int, maxCacheSize: Int) : Seria
5454
val superJmClass = if (!clazz.isInterface) {
5555
clazz.superclass?.let {
5656
// Stop parsing when `Object` is reached
57-
if (it != Any::class.java) getJmClass(it) else null
57+
if (it != ANY_CLASS) getJmClass(it) else null
5858
}
5959
} else {
6060
null

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMethod
1212
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter
1313
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector
1414
import com.fasterxml.jackson.databind.util.Converter
15-
import io.github.projectmapk.jackson.module.kogera.KotlinDuration
15+
import io.github.projectmapk.jackson.module.kogera.JSON_K_UNBOX_CLASS
16+
import io.github.projectmapk.jackson.module.kogera.KOTLIN_DURATION_CLASS
1617
import io.github.projectmapk.jackson.module.kogera.ReflectionCache
17-
import io.github.projectmapk.jackson.module.kogera.annotation.JsonKUnbox
1818
import io.github.projectmapk.jackson.module.kogera.isUnboxableValueClass
1919
import io.github.projectmapk.jackson.module.kogera.reconstructClassOrNull
2020
import io.github.projectmapk.jackson.module.kogera.ser.KotlinDurationValueToJavaDurationConverter
@@ -74,15 +74,15 @@ internal class KotlinFallbackAnnotationIntrospector(
7474
override fun findSerializationConverter(a: Annotated): Converter<*, *>? = when (a) {
7575
// Find a converter to handle the case where the getter returns an unboxed value from the value class.
7676
is AnnotatedMethod -> cache.findBoxedReturnType(a.member)?.let {
77-
if (useJavaDurationConversion && it == KotlinDuration::class.java) {
78-
if (a.rawReturnType == KotlinDuration::class.java) {
77+
if (useJavaDurationConversion && it == KOTLIN_DURATION_CLASS) {
78+
if (a.rawReturnType == KOTLIN_DURATION_CLASS) {
7979
KotlinToJavaDurationConverter
8080
} else {
8181
KotlinDurationValueToJavaDurationConverter
8282
}
8383
} else {
8484
// If JsonUnbox is specified, the unboxed getter is used as is.
85-
if (a.hasAnnotation(JsonKUnbox::class.java) || it.isAnnotationPresent(JsonKUnbox::class.java)) {
85+
if (a.hasAnnotation(JSON_K_UNBOX_CLASS) || it.isAnnotationPresent(JSON_K_UNBOX_CLASS)) {
8686
null
8787
} else {
8888
cache.getValueClassBoxConverter(a.rawReturnType, it)
@@ -95,7 +95,7 @@ internal class KotlinFallbackAnnotationIntrospector(
9595

9696
private fun lookupKotlinTypeConverter(a: AnnotatedClass) = when {
9797
Sequence::class.java.isAssignableFrom(a.rawType) -> SequenceToIteratorConverter(a.type)
98-
KotlinDuration::class.java == a.rawType -> KotlinToJavaDurationConverter.takeIf { useJavaDurationConversion }
98+
KOTLIN_DURATION_CLASS == a.rawType -> KotlinToJavaDurationConverter.takeIf { useJavaDurationConversion }
9999
else -> null
100100
}
101101

0 commit comments

Comments
 (0)