Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
k163377 committed Feb 2, 2025
1 parent fe85552 commit 9b44607
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.module.kotlin.WrapsNullableValueClassDeserializer
import com.fasterxml.jackson.databind.KeyDeserializer as JacksonKeyDeserializer

@JvmInline
value class Primitive(val v: Int) {
class Deserializer : StdDeserializer<Primitive>(Primitive::class.java) {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Primitive = Primitive(p.intValue + 100)
}

class KeyDeserializer : JacksonKeyDeserializer() {
override fun deserializeKey(key: String, ctxt: DeserializationContext) = Primitive(key.toInt() + 100)
}
}

@JvmInline
Expand All @@ -18,6 +23,10 @@ value class NonNullObject(val v: String) {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): NonNullObject =
NonNullObject(p.valueAsString + "-deser")
}

class KeyDeserializer : JacksonKeyDeserializer() {
override fun deserializeKey(key: String, ctxt: DeserializationContext) = NonNullObject("$key-deser")
}
}

@JvmInline
Expand All @@ -28,4 +37,8 @@ value class NullableObject(val v: String?) {

override fun getBoxedNullValue(): NullableObject = NullableObject("null-value-deser")
}

class KeyDeserializer : JacksonKeyDeserializer() {
override fun deserializeKey(key: String, ctxt: DeserializationContext) = NullableObject("$key-deser")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.mapKey

import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.module.kotlin.defaultMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.NonNullObject
import com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.NullableObject
import com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.Primitive
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import java.lang.reflect.InvocationTargetException
import com.fasterxml.jackson.databind.KeyDeserializer as JacksonKeyDeserializer

class WithoutCustomDeserializeMethodTest {
companion object {
val throwable = IllegalArgumentException("test")
}

@Nested
inner class DirectDeserialize {
@Test
fun primitive() {
val result = defaultMapper.readValue<Map<Primitive, String?>>("""{"1":null}""")
assertEquals(mapOf(Primitive(1) to null), result)
}

@Test
fun nonNullObject() {
val result = defaultMapper.readValue<Map<NonNullObject, String?>>("""{"foo":null}""")
assertEquals(mapOf(NonNullObject("foo") to null), result)
}

@Test
fun nullableObject() {
val result = defaultMapper.readValue<Map<NullableObject, String?>>("""{"bar":null}""")
assertEquals(mapOf(NullableObject("bar") to null), result)
}
}

data class Dst(
val p: Map<Primitive, String?>,
val nn: Map<NonNullObject, String?>,
val n: Map<NullableObject, String?>
)

@Test
fun wrapped() {
val src = """
{
"p":{"1":null},
"nn":{"foo":null},
"n":{"bar":null}
}
""".trimIndent()
val result = defaultMapper.readValue<Dst>(src)
val expected = Dst(
mapOf(Primitive(1) to null),
mapOf(NonNullObject("foo") to null),
mapOf(NullableObject("bar") to null)
)

assertEquals(expected, result)
}

@JvmInline
value class HasCheckConstructor(val value: Int) {
init {
if (value < 0) throw throwable
}
}

@Test
fun callConstructorCheckTest() {
val e = assertThrows<InvocationTargetException> {
defaultMapper.readValue<Map<HasCheckConstructor, String?>>("""{"-1":null}""")
}
assertTrue(e.cause === throwable)
}

data class Wrapped(val first: String, val second: String) {
class KeyDeserializer : JacksonKeyDeserializer() {
override fun deserializeKey(key: String, ctxt: DeserializationContext) =
key.split("-").let { Wrapped(it[0], it[1]) }
}
}

@JvmInline
value class Wrapper(val w: Wrapped)

@Test
fun wrappedCustomObject() {
// If a type that cannot be deserialized is specified, the default is an error.
val thrown = assertThrows<JsonMappingException> {
defaultMapper.readValue<Map<Wrapper, String?>>("""{"foo-bar":null}""")
}
assertTrue(thrown.cause is InvalidDefinitionException)

val mapper = jacksonObjectMapper()
.registerModule(
object : SimpleModule() {
init { addKeyDeserializer(Wrapped::class.java, Wrapped.KeyDeserializer()) }
}
)

val result = mapper.readValue<Map<Wrapper, String?>>("""{"foo-bar":null}""")
val expected = mapOf(Wrapper(Wrapped("foo", "bar")) to null)

assertEquals(expected, result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.mapKey.keyDeserializer

import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.NonNullObject
import com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.NullableObject
import com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.Primitive
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test

class SpecifiedForObjectMapperTest {
companion object {
val mapper = jacksonObjectMapper().apply {
val module = SimpleModule().apply {
this.addKeyDeserializer(Primitive::class.java, Primitive.KeyDeserializer())
this.addKeyDeserializer(NonNullObject::class.java, NonNullObject.KeyDeserializer())
this.addKeyDeserializer(NullableObject::class.java, NullableObject.KeyDeserializer())
}
this.registerModule(module)
}
}

@Nested
inner class DirectDeserialize {
@Test
fun primitive() {
val result = mapper.readValue<Map<Primitive, String?>>("""{"1":null}""")
assertEquals(mapOf(Primitive(101) to null), result)
}

@Test
fun nonNullObject() {
val result = mapper.readValue<Map<NonNullObject, String?>>("""{"foo":null}""")
assertEquals(mapOf(NonNullObject("foo-deser") to null), result)
}

@Test
fun nullableObject() {
val result = mapper.readValue<Map<NullableObject, String?>>("""{"bar":null}""")
assertEquals(mapOf(NullableObject("bar-deser") to null), result)
}
}

data class Dst(
val p: Map<Primitive, String?>,
val nn: Map<NonNullObject, String?>,
val n: Map<NullableObject, String?>
)

@Test
fun wrapped() {
val src = """
{
"p":{"1":null},
"nn":{"foo":null},
"n":{"bar":null}
}
""".trimIndent()
val result = mapper.readValue<Dst>(src)
val expected = Dst(
mapOf(Primitive(101) to null),
mapOf(NonNullObject("foo-deser") to null),
mapOf(NullableObject("bar-deser") to null)
)

assertEquals(expected, result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.mapKey.keyDeserializer.byAnnotation

import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.module.kotlin.defaultMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import com.fasterxml.jackson.databind.KeyDeserializer as JacksonKeyDeserializer

class SpecifiedForClassTest {
@JsonDeserialize(keyUsing = Value.KeyDeserializer::class)
@JvmInline
value class Value(val v: Int) {
class KeyDeserializer : JacksonKeyDeserializer() {
override fun deserializeKey(key: String, ctxt: DeserializationContext) = Value(key.toInt() + 100)
}
}

@Test
fun directDeserTest() {
val result = defaultMapper.readValue<Map<Value, String?>>("""{"1":null}""")

assertEquals(mapOf(Value(101) to null), result)
}

data class Wrapper(val v: Map<Value, String?>)

@Test
fun paramDeserTest() {
val mapper = jacksonObjectMapper()
val result = mapper.readValue<Wrapper>("""{"v":{"1":null}}""")

assertEquals(Wrapper(mapOf(Value(101) to null)), result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.fasterxml.jackson.module.kotlin.kogeraIntegration.deser.valueClass.mapKey.keyDeserializer.byAnnotation

import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import com.fasterxml.jackson.databind.KeyDeserializer as JacksonKeyDeserializer

class SpecifiedForPropertyTest {
@JvmInline
value class Value(val v: Int) {
class KeyDeserializer : JacksonKeyDeserializer() {
override fun deserializeKey(key: String, ctxt: DeserializationContext) = Value(key.toInt() + 100)
}
}

data class Wrapper(@JsonDeserialize(keyUsing = Value.KeyDeserializer::class) val v: Map<Value, String?>)

@Test
fun paramDeserTest() {
val mapper = jacksonObjectMapper()
val result = mapper.readValue<Wrapper>("""{"v":{"1":null}}""")

assertEquals(Wrapper(mapOf(Value(101) to null)), result)
}
}

0 comments on commit 9b44607

Please sign in to comment.