diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index b8c606c07..3337ab9ea 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -50,3 +50,7 @@ Drew Stephens (dinomite@github) Mateusz Stefek (MateuszStefek@github) * Reported #321: Make MissingKotlinParameterException a descendant of MismatchedInputException + +John Flynn (Neuman968@github) +* Contributed extension methods for SimpleModule to add serializer and deserializer extension functions for KClass #322 + (2.12.x) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 964e1bee3..131936b78 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -4,6 +4,12 @@ Project: jackson-module-kotlin === Releases === ------------------------------------------------------------------------ +2.12.0 (not yet released) + +#322 Added extension methods to SimpleModule addSerializer and addDeserializer to support KClass arguments that + register the serializer/deserializer for both the java type and java class. +- + 2.11.1 (not yet released) - diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt index 079b0e607..5e1b11bb1 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt @@ -7,10 +7,14 @@ import com.fasterxml.jackson.databind.JsonMappingException import com.fasterxml.jackson.databind.MappingIterator import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectReader +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.JsonSerializer import java.io.File import java.io.InputStream import java.io.Reader import java.net.URL +import kotlin.reflect.KClass fun jacksonObjectMapper(): ObjectMapper = ObjectMapper().registerKotlinModule() fun ObjectMapper.registerKotlinModule(): ObjectMapper = this.registerModule(KotlinModule()) @@ -35,4 +39,14 @@ inline fun ObjectReader.readValuesTyped(jp: JsonParser): Iterator inline fun ObjectReader.treeToValue(n: TreeNode): T? = treeToValue(n, T::class.java) internal fun JsonMappingException.wrapWithPath(refFrom: Any?, refFieldName: String) = JsonMappingException.wrapWithPath(this, refFrom, refFieldName) -internal fun JsonMappingException.wrapWithPath(refFrom: Any?, index: Int) = JsonMappingException.wrapWithPath(this, refFrom, index) \ No newline at end of file +internal fun JsonMappingException.wrapWithPath(refFrom: Any?, index: Int) = JsonMappingException.wrapWithPath(this, refFrom, index) + +inline fun SimpleModule.addSerializer(kClass: KClass, serializer: JsonSerializer) = this.apply { + addSerializer(kClass.java, serializer) + addSerializer(kClass.javaObjectType, serializer) +} + +inline fun SimpleModule.addDeserializer(kClass: KClass, deserializer: JsonDeserializer) = this.apply { + addDeserializer(kClass.java, deserializer) + addDeserializer(kClass.javaObjectType, deserializer) +} \ No newline at end of file diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/KClassSerializerDeserializerTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/KClassSerializerDeserializerTest.kt new file mode 100644 index 000000000..649b8aa63 --- /dev/null +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/KClassSerializerDeserializerTest.kt @@ -0,0 +1,65 @@ +package com.fasterxml.jackson.module.kotlin.test + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.module.kotlin.addDeserializer +import com.fasterxml.jackson.module.kotlin.addSerializer +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.Test +import java.math.BigDecimal +import java.math.RoundingMode + +class KClassSerializerDeserializerTest { + + val objectMapper = jacksonObjectMapper() + .registerModule(SimpleModule() + .addSerializer(Double::class, RoundingSerializer()) + .addDeserializer(Double::class, RoundingDeserializer())) + + + @Test + fun `test custom serializer expecting object serialized with rounding serializer applied`() { + val jsonString = objectMapper.writeValueAsString(TestDoubleData(nonNullVal = 1.5567, nullVal = 1.5678)) + val testResult = objectMapper.readValue(jsonString, TestDoubleData::class.java) + assertThat(testResult.nonNullVal, equalTo(1.56)) + assertThat(testResult.nullVal, equalTo(1.57)) + } + + @Test + fun `test custom deserializer expecting object deserialized with rounding deserializer applied`() { + val testResult = objectMapper.readValue(""" + { + "nonNullVal":1.5567, + "nullVal":1.5678 + } + """.trimIndent()) + assertThat(testResult.nonNullVal, equalTo(1.56)) + assertThat(testResult.nullVal, equalTo(1.57)) + } +} + +data class TestDoubleData( + val nonNullVal: Double, + val nullVal: Double? +) + +class RoundingSerializer : JsonSerializer() { + override fun serialize(value: Double?, gen: JsonGenerator?, serializers: SerializerProvider?) { + value?.let { + gen?.writeNumber(BigDecimal(it).setScale(2, RoundingMode.HALF_UP)) + } + } +} + +class RoundingDeserializer : JsonDeserializer() { + override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Double? { + return BigDecimal(p?.valueAsString) + .setScale(2, RoundingMode.HALF_UP) + .toDouble() + } +} \ No newline at end of file