diff --git a/.github/workflows/test-main.yml b/.github/workflows/test-main.yml index e5a08200..8e8cdfe1 100644 --- a/.github/workflows/test-main.yml +++ b/.github/workflows/test-main.yml @@ -42,7 +42,7 @@ jobs: # LTS versions, latest version (if exists) java-version: [ '17', '21', '24' ] # Minimum version, latest release version, latest pre-release version (if exists) - kotlin: ['2.0.21', '2.1.20', '2.2.0-RC'] + kotlin: ['2.0.21', '2.1.21', '2.2.0'] env: KOTLIN_VERSION: ${{ matrix.kotlin }} name: "Kotlin ${{ matrix.kotlin }} - Java ${{ matrix.java-version }}" diff --git a/.junie/guidelines.md b/.junie/guidelines.md new file mode 100644 index 00000000..b6d842b1 --- /dev/null +++ b/.junie/guidelines.md @@ -0,0 +1,6 @@ +# Spring Boot +## 1. Perform formatting just before completing the task + +```bash +./gradlew formatKotlin +``` diff --git a/build.gradle.kts b/build.gradle.kts index d8d577a1..8dc2e27c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,7 +18,7 @@ val jacksonVersion = libs.versions.jackson.get() val generatedSrcPath = "${layout.buildDirectory.get()}/generated/kotlin" group = groupStr -version = "${jacksonVersion}-beta25" +version = "${jacksonVersion}-beta26" repositories { mavenCentral() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 614c698c..3aa8f54f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,9 +1,9 @@ [versions] kotlin = "2.0.21" # Mainly for CI, it can be rewritten by environment variable. -jackson = "2.19.0" +jackson = "2.19.1" # test libs -junit = "5.13.1" +junit = "5.13.2" [libraries] kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib" } @@ -14,7 +14,7 @@ jackson-annotations = { module = "com.fasterxml.jackson.core:jackson-annotations # test libs kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect" } junit-bom = { module = "org.junit:junit-bom", version.ref = "junit" } -mockk = "io.mockk:mockk:1.14.2" +mockk = "io.mockk:mockk:1.14.4" jackson-xml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-xml", version.ref = "jackson" } jackson-csv = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-csv", version.ref = "jackson" } jackson-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" } diff --git a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt index d77871e7..ab528715 100644 --- a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt +++ b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt @@ -71,15 +71,15 @@ internal val STRING_CLASS = String::class.java internal val JAVA_UUID_CLASS = java.util.UUID::class.java internal val ANY_CLASS = Any::class.java -internal val ANY_TO_ANY_METHOD_TYPE = MethodType.methodType(ANY_CLASS, ANY_CLASS) -internal val ANY_TO_INT_METHOD_TYPE = MethodType.methodType(INT_CLASS, ANY_CLASS) -internal val ANY_TO_LONG_METHOD_TYPE = MethodType.methodType(LONG_CLASS, ANY_CLASS) -internal val ANY_TO_STRING_METHOD_TYPE = MethodType.methodType(STRING_CLASS, ANY_CLASS) -internal val ANY_TO_JAVA_UUID_METHOD_TYPE = MethodType.methodType(JAVA_UUID_CLASS, ANY_CLASS) -internal val INT_TO_ANY_METHOD_TYPE = MethodType.methodType(ANY_CLASS, INT_CLASS) -internal val LONG_TO_ANY_METHOD_TYPE = MethodType.methodType(ANY_CLASS, LONG_CLASS) -internal val STRING_TO_ANY_METHOD_TYPE = MethodType.methodType(ANY_CLASS, STRING_CLASS) -internal val JAVA_UUID_TO_ANY_METHOD_TYPE = MethodType.methodType(ANY_CLASS, JAVA_UUID_CLASS) +internal val ANY_TO_ANY_METHOD_TYPE by lazy { MethodType.methodType(ANY_CLASS, ANY_CLASS) } +internal val ANY_TO_INT_METHOD_TYPE by lazy { MethodType.methodType(INT_CLASS, ANY_CLASS) } +internal val ANY_TO_LONG_METHOD_TYPE by lazy { MethodType.methodType(LONG_CLASS, ANY_CLASS) } +internal val ANY_TO_STRING_METHOD_TYPE by lazy { MethodType.methodType(STRING_CLASS, ANY_CLASS) } +internal val ANY_TO_JAVA_UUID_METHOD_TYPE by lazy { MethodType.methodType(JAVA_UUID_CLASS, ANY_CLASS) } +internal val INT_TO_ANY_METHOD_TYPE by lazy { MethodType.methodType(ANY_CLASS, INT_CLASS) } +internal val LONG_TO_ANY_METHOD_TYPE by lazy { MethodType.methodType(ANY_CLASS, LONG_CLASS) } +internal val STRING_TO_ANY_METHOD_TYPE by lazy { MethodType.methodType(ANY_CLASS, STRING_CLASS) } +internal val JAVA_UUID_TO_ANY_METHOD_TYPE by lazy { MethodType.methodType(ANY_CLASS, JAVA_UUID_CLASS) } internal fun unreflect(method: Method): MethodHandle = MethodHandles.lookup().unreflect(method) internal fun unreflectAsType(method: Method, type: MethodType): MethodHandle = unreflect(method).asType(type) diff --git a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ser/Converters.kt b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ser/Converters.kt index caacdad3..5b1f44ef 100644 --- a/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ser/Converters.kt +++ b/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ser/Converters.kt @@ -3,10 +3,10 @@ package io.github.projectmapk.jackson.module.kogera.ser import com.fasterxml.jackson.databind.JavaType import com.fasterxml.jackson.databind.type.TypeFactory import com.fasterxml.jackson.databind.util.StdConverter -import io.github.projectmapk.jackson.module.kogera.GenericValueClassBoxConverter import io.github.projectmapk.jackson.module.kogera.JavaDuration import io.github.projectmapk.jackson.module.kogera.KOTLIN_DURATION_CLASS import io.github.projectmapk.jackson.module.kogera.KotlinDuration +import io.github.projectmapk.jackson.module.kogera.LongValueClassBoxConverter import kotlin.time.toJavaDuration internal class SequenceToIteratorConverter(private val input: JavaType) : StdConverter, Iterator<*>>() { @@ -21,7 +21,7 @@ internal class SequenceToIteratorConverter(private val input: JavaType) : StdCon } internal object KotlinDurationValueToJavaDurationConverter : StdConverter() { - private val boxConverter by lazy { GenericValueClassBoxConverter(Long::class.java, KOTLIN_DURATION_CLASS) } + private val boxConverter by lazy { LongValueClassBoxConverter(KOTLIN_DURATION_CLASS) } override fun convert(value: Long): JavaDuration = KotlinToJavaDurationConverter.convert(boxConverter.convert(value)) } diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NonNullObjectTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NonNullObjectTest.kt new file mode 100644 index 00000000..f4207562 --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NonNullObjectTest.kt @@ -0,0 +1,37 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonKey + +import com.fasterxml.jackson.annotation.JsonKey +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class NonNullObjectTest { + @JvmInline + value class NonNull(val v: String) { + @JsonKey + fun jsonValue() = v + "_modified" + } + + @Test + fun nonNullTest() { + assertEquals( + """{"test_modified":null}""", + defaultMapper.writeValueAsString(mapOf(NonNull("test") to null)), + ) + } + + @JvmInline + value class Nullable(val v: String) { + @JsonKey + fun jsonValue() = v.takeIf { it.length % 2 == 0 }?.let { it + "_modified" } + } + + // The case of returning null as a key is unnecessary because it will result in an error + @Test + fun nullableTest() { + assertEquals( + """{"test_modified":null}""", + defaultMapper.writeValueAsString(mapOf(Nullable("test") to null)), + ) + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NullableObjectTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NullableObjectTest.kt new file mode 100644 index 00000000..50f2326b --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NullableObjectTest.kt @@ -0,0 +1,23 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonKey + +import com.fasterxml.jackson.annotation.JsonKey +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class NullableObjectTest { + @JvmInline + value class Value(val v: String?) { + @JsonKey + fun jsonValue() = v?.let { it + "_modified" } + } + + // The case of returning null as a key is unnecessary because it will result in an error + @Test + fun test() { + assertEquals( + """{"test_modified":null}""", + defaultMapper.writeValueAsString(mapOf(Value("test") to null)), + ) + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NullablePrimitiveTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NullablePrimitiveTest.kt new file mode 100644 index 00000000..a12e79d4 --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/NullablePrimitiveTest.kt @@ -0,0 +1,23 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonKey + +import com.fasterxml.jackson.annotation.JsonKey +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class NullablePrimitiveTest { + @JvmInline + value class Value(val v: Int?) { + @JsonKey + fun jsonValue() = v?.let { it + 100 } + } + + // The case of returning null as a key is unnecessary because it will result in an error + @Test + fun test() { + assertEquals( + """{"100":null}""", + defaultMapper.writeValueAsString(mapOf(Value(0) to null)), + ) + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/PrimitiveTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/PrimitiveTest.kt new file mode 100644 index 00000000..9aba8b18 --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/PrimitiveTest.kt @@ -0,0 +1,37 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonKey + +import com.fasterxml.jackson.annotation.JsonKey +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class PrimitiveTest { + @JvmInline + value class NonNull(val v: Int) { + @JsonKey + fun jsonValue() = v + 100 + } + + @Test + fun nonNullTest() { + assertEquals( + """{"100":null}""", + defaultMapper.writeValueAsString(mapOf(NonNull(0) to null)), + ) + } + + @JvmInline + value class Nullable(val v: Int) { + @JsonKey + fun jsonValue() = v.takeIf { it % 2 == 0 }?.let { it + 100 } + } + + // The case of returning null as a key is unnecessary because it will result in an error + @Test + fun nullableTest() { + assertEquals( + """{"100":null}""", + defaultMapper.writeValueAsString(mapOf(Nullable(0) to null)), + ) + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/TwoUnitPrimitiveTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/TwoUnitPrimitiveTest.kt new file mode 100644 index 00000000..8a657764 --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonKey/TwoUnitPrimitiveTest.kt @@ -0,0 +1,37 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonKey + +import com.fasterxml.jackson.annotation.JsonKey +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class TwoUnitPrimitiveTest { + @JvmInline + value class NonNull(val v: Long) { + @JsonKey + fun jsonValue() = v + 100 + } + + @Test + fun nonNullTest() { + assertEquals( + """{"100":null}""", + defaultMapper.writeValueAsString(mapOf(NonNull(0) to null)), + ) + } + + @JvmInline + value class Nullable(val v: Long) { + @JsonKey + fun jsonValue() = v.takeIf { it % 2L == 0L }?.let { it + 100 } + } + + // The case of returning null as a key is unnecessary because it will result in an error + @Test + fun nullableTest() { + assertEquals( + """{"100":null}""", + defaultMapper.writeValueAsString(mapOf(Nullable(0) to null)), + ) + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NonNullObjectTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NonNullObjectTest.kt new file mode 100644 index 00000000..c44073d3 --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NonNullObjectTest.kt @@ -0,0 +1,85 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonValue + +import com.fasterxml.jackson.annotation.JsonValue +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class NonNullObjectTest { + @JvmInline + value class NonNull(val v: String) { + @JsonValue + fun jsonValue() = v + "_modified" + } + + data class NonNullDto(val v: NonNull) + + @Nested + inner class NonNullTest { + @Test + fun direct() { + assertEquals( + "\"test_modified\"", + defaultMapper.writeValueAsString(NonNull("test")), + ) + } + + @Test + fun asProperty() { + assertEquals( + """{"v":"test_modified"}""", + defaultMapper.writeValueAsString(NonNullDto(NonNull("test"))), + ) + } + } + + @JvmInline + value class Nullable(val v: String) { + @JsonValue + fun jsonValue() = v.takeIf { it.length % 2 == 0 }?.let { it + "_modified" } + } + + data class NullableDto(val v: Nullable) + + @Nested + inner class NullableTest { + @Nested + inner class DirectTest { + @Test + fun nonNull() { + assertEquals( + "\"even_modified\"", + defaultMapper.writeValueAsString(Nullable("even")), + ) + } + + @Test + fun `null`() { + assertEquals( + "null", + defaultMapper.writeValueAsString(Nullable("odd")), + ) + } + } + + @Nested + inner class AsPropertyTest { + @Test + fun nonNull() { + assertEquals( + """{"v":"even_modified"}""", + defaultMapper.writeValueAsString(NullableDto(Nullable("even"))), + ) + } + + @Test + fun `null`() { + assertEquals( + """{"v":null}""", + defaultMapper.writeValueAsString(NullableDto(Nullable("odd"))), + ) + } + } + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NullableObjectTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NullableObjectTest.kt new file mode 100644 index 00000000..a76cd4ab --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NullableObjectTest.kt @@ -0,0 +1,55 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonValue + +import com.fasterxml.jackson.annotation.JsonValue +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class NullableObjectTest { + @JvmInline + value class Value(val v: String?) { + @JsonValue + fun jsonValue() = v?.let { it + "_modified" } + } + + @Nested + inner class DirectTest { + @Test + fun nonNull() { + assertEquals( + "\"test_modified\"", + defaultMapper.writeValueAsString(Value("test")), + ) + } + + @Test + fun `null`() { + assertEquals( + "null", + defaultMapper.writeValueAsString(Value(null)), + ) + } + } + + data class Dto(val v: Value) + + @Nested + inner class AsPropertyTest { + @Test + fun nonNull() { + assertEquals( + """{"v":"test_modified"}""", + defaultMapper.writeValueAsString(Dto(Value("test"))), + ) + } + + @Test + fun `null`() { + assertEquals( + """{"v":null}""", + defaultMapper.writeValueAsString(Dto(Value(null))), + ) + } + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NullablePrimitiveTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NullablePrimitiveTest.kt new file mode 100644 index 00000000..a895e480 --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/NullablePrimitiveTest.kt @@ -0,0 +1,55 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonValue + +import com.fasterxml.jackson.annotation.JsonValue +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class NullablePrimitiveTest { + @JvmInline + value class Value(val v: Int?) { + @JsonValue + fun jsonValue() = v?.let { it + 100 } + } + + @Nested + inner class DirectTest { + @Test + fun nonNull() { + assertEquals( + "100", + defaultMapper.writeValueAsString(Value(0)), + ) + } + + @Test + fun `null`() { + assertEquals( + "null", + defaultMapper.writeValueAsString(Value(null)), + ) + } + } + + data class Dto(val v: Value) + + @Nested + inner class AsPropertyTest { + @Test + fun nonNull() { + assertEquals( + """{"v":100}""", + defaultMapper.writeValueAsString(Dto(Value(0))), + ) + } + + @Test + fun `null`() { + assertEquals( + """{"v":null}""", + defaultMapper.writeValueAsString(Dto(Value(null))), + ) + } + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/PrimitiveTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/PrimitiveTest.kt new file mode 100644 index 00000000..52027222 --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/PrimitiveTest.kt @@ -0,0 +1,85 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonValue + +import com.fasterxml.jackson.annotation.JsonValue +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class PrimitiveTest { + @JvmInline + value class NonNull(val v: Int) { + @JsonValue + fun jsonValue() = v + 100 + } + + data class NonNullDto(val v: NonNull) + + @Nested + inner class NonNullTest { + @Test + fun direct() { + assertEquals( + "100", + defaultMapper.writeValueAsString(NonNull(0)), + ) + } + + @Test + fun asProperty() { + assertEquals( + """{"v":100}""", + defaultMapper.writeValueAsString(NonNullDto(NonNull(0))), + ) + } + } + + @JvmInline + value class Nullable(val v: Int) { + @JsonValue + fun jsonValue() = v.takeIf { it % 2 == 0 }?.let { it + 100 } + } + + data class NullableDto(val v: Nullable) + + @Nested + inner class NullableTest { + @Nested + inner class DirectTest { + @Test + fun nonNull() { + assertEquals( + "100", + defaultMapper.writeValueAsString(Nullable(0)), + ) + } + + @Test + fun `null`() { + assertEquals( + "null", + defaultMapper.writeValueAsString(Nullable(1)), + ) + } + } + + @Nested + inner class AsPropertyTest { + @Test + fun nonNull() { + assertEquals( + """{"v":100}""", + defaultMapper.writeValueAsString(NullableDto(Nullable(0))), + ) + } + + @Test + fun `null`() { + assertEquals( + """{"v":null}""", + defaultMapper.writeValueAsString(NullableDto(Nullable(1))), + ) + } + } + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/TwoUnitPrimitiveTest.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/TwoUnitPrimitiveTest.kt new file mode 100644 index 00000000..da12b04b --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zIntegration/ser/valueClass/jsonValue/TwoUnitPrimitiveTest.kt @@ -0,0 +1,85 @@ +package io.github.projectmapk.jackson.module.kogera.zIntegration.ser.valueClass.jsonValue + +import com.fasterxml.jackson.annotation.JsonValue +import io.github.projectmapk.jackson.module.kogera.defaultMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class TwoUnitPrimitiveTest { + @JvmInline + value class NonNull(val v: Long) { + @JsonValue + fun jsonValue() = v + 100 + } + + data class NonNullDto(val v: NonNull) + + @Nested + inner class NonNullTest { + @Test + fun direct() { + assertEquals( + "100", + defaultMapper.writeValueAsString(NonNull(0)), + ) + } + + @Test + fun asProperty() { + assertEquals( + """{"v":100}""", + defaultMapper.writeValueAsString(NonNullDto(NonNull(0))), + ) + } + } + + @JvmInline + value class Nullable(val v: Long) { + @JsonValue + fun jsonValue() = v.takeIf { it % 2L == 0L }?.let { it + 100 } + } + + data class NullableDto(val v: Nullable) + + @Nested + inner class NullableTest { + @Nested + inner class DirectTest { + @Test + fun nonNull() { + assertEquals( + "100", + defaultMapper.writeValueAsString(Nullable(0)), + ) + } + + @Test + fun `null`() { + assertEquals( + "null", + defaultMapper.writeValueAsString(Nullable(1)), + ) + } + } + + @Nested + inner class AsPropertyTest { + @Test + fun nonNull() { + assertEquals( + """{"v":100}""", + defaultMapper.writeValueAsString(NullableDto(Nullable(0))), + ) + } + + @Test + fun `null`() { + assertEquals( + """{"v":null}""", + defaultMapper.writeValueAsString(NullableDto(Nullable(1))), + ) + } + } + } +} diff --git a/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zPorted/test/github/GitHub976.kt b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zPorted/test/github/GitHub976.kt new file mode 100644 index 00000000..c3077dab --- /dev/null +++ b/src/test/kotlin/io/github/projectmapk/jackson/module/kogera/zPorted/test/github/GitHub976.kt @@ -0,0 +1,21 @@ +package io.github.projectmapk.jackson.module.kogera.zPorted.test.github + +import com.fasterxml.jackson.databind.exc.InvalidNullException +import io.github.projectmapk.jackson.module.kogera.KotlinFeature +import io.github.projectmapk.jackson.module.kogera.jacksonObjectMapper +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class GitHub976 { + data class PrimitiveList(val list: List) + + @Test + fun strictNullChecks() { + val om = jacksonObjectMapper { + enable(KotlinFeature.StrictNullChecks) + } + assertThrows { + om.readValue("""{"list": [""] }""", PrimitiveList::class.java) + } + } +}