Skip to content

Commit

Permalink
Merge pull request #104 from ProjectMapK/fix-sequence-ser
Browse files Browse the repository at this point in the history
Import from jackson-module-kotlin#675
  • Loading branch information
k163377 committed May 6, 2023
2 parents da8ccba + 46303a8 commit d418750
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.fasterxml.jackson.module.kotlin.findPropertyByGetter
import com.fasterxml.jackson.module.kotlin.isNullable
import com.fasterxml.jackson.module.kotlin.isUnboxableValueClass
import com.fasterxml.jackson.module.kotlin.reconstructClassOrNull
import com.fasterxml.jackson.module.kotlin.ser.SequenceToIteratorConverter
import com.fasterxml.jackson.module.kotlin.toSignature
import kotlinx.metadata.jvm.fieldSignature
import kotlinx.metadata.jvm.setterSignature
Expand Down Expand Up @@ -102,9 +103,15 @@ internal class KotlinFallbackAnnotationIntrospector(
}
}

// Find a converter to handle the case where the getter returns an unboxed value from the value class.
override fun findSerializationConverter(a: Annotated): Converter<*, *>? = (a as? AnnotatedMethod)?.let { _ ->
cache.findValueClassReturnType(a)?.let { cache.getValueClassBoxConverter(a.rawReturnType, it) }
override fun findSerializationConverter(a: Annotated): Converter<*, *>? = when (a) {
// Find a converter to handle the case where the getter returns an unboxed value from the value class.
is AnnotatedMethod -> cache.findValueClassReturnType(a)
?.let { cache.getValueClassBoxConverter(a.rawReturnType, it) }
is AnnotatedClass ->
a
.takeIf { Sequence::class.java.isAssignableFrom(it.rawType) }
?.let { SequenceToIteratorConverter(it.type) }
else -> null
}

// Determine if the unbox result of value class is nullable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
package com.fasterxml.jackson.module.kotlin.ser

import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer
import com.fasterxml.jackson.databind.type.TypeFactory
import com.fasterxml.jackson.databind.util.StdConverter

internal class SequenceToIteratorConverter(private val input: JavaType) : StdConverter<Sequence<*>, Iterator<*>>() {
override fun convert(value: Sequence<*>): Iterator<*> = value.iterator()

override fun getInputType(typeFactory: TypeFactory): JavaType = input

// element-type may not be obtained, so a null check is required
override fun getOutputType(typeFactory: TypeFactory): JavaType = input.containedType(0)
?.let { typeFactory.constructCollectionLikeType(Iterator::class.java, it) }
?: typeFactory.constructType(Iterator::class.java)
}

// S is nullable because value corresponds to a nullable value class
// @see KotlinFallbackAnnotationIntrospector.findNullSerializer
internal class ValueClassBoxConverter<S : Any?, D : Any>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.math.BigInteger

internal object SequenceSerializer : StdSerializer<Sequence<*>>(Sequence::class.java) {
override fun serialize(value: Sequence<*>, gen: JsonGenerator, provider: SerializerProvider) {
provider.defaultSerializeValue(value.iterator(), gen)
}
}

internal object UByteSerializer : StdSerializer<UByte>(UByte::class.java) {
override fun serialize(value: UByte, gen: JsonGenerator, provider: SerializerProvider) =
gen.writeNumber(value.toShort())
Expand Down Expand Up @@ -91,7 +85,6 @@ internal class KotlinSerializers : Serializers.Base() {
val rawClass = type.rawClass

return when {
Sequence::class.java.isAssignableFrom(rawClass) -> SequenceSerializer
UByte::class.java.isAssignableFrom(rawClass) -> UByteSerializer
UShort::class.java.isAssignableFrom(rawClass) -> UShortSerializer
UInt::class.java.isAssignableFrom(rawClass) -> UIntSerializer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.fasterxml.jackson.module.kotlin._ported.test

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.jupiter.api.Assertions.assertEquals
Expand Down Expand Up @@ -41,4 +45,39 @@ class TestSequenceDeserializer {
val result = objectMapper.writeValueAsString(data)
assertEquals("{\"value\":[]}", result)
}

class ContentSer : StdSerializer<String>(String::class.java) {
override fun serialize(value: String, gen: JsonGenerator, provider: SerializerProvider) {
provider.defaultSerializeValue("$value-ser", gen)
}
}

data class ListWrapper(
@JsonSerialize(contentUsing = ContentSer::class) val value: List<String>
)

data class SequenceWrapper(
@JsonSerialize(contentUsing = ContentSer::class)
val value: Sequence<String>
)

@Test
fun contentUsingTest() {
val mapper = jacksonObjectMapper()

val listResult = mapper.writeValueAsString(ListWrapper(listOf("foo")))
val sequenceResult = mapper.writeValueAsString(SequenceWrapper(sequenceOf("foo")))

assertEquals("""{"value":["foo-ser"]}""", sequenceResult)
assertEquals(listResult, sequenceResult)
}

// @see #674
@Test
fun sequenceOfTest() {
val mapper = jacksonObjectMapper()
val result = mapper.writeValueAsString(sequenceOf("foo"))

assertEquals("""["foo"]""", result)
}
}

0 comments on commit d418750

Please sign in to comment.