Skip to content

Commit b91f5c2

Browse files
authored
Merge pull request #675 from k163377/seq-ser
Modified to use `Converter` in `Sequence` serialization
2 parents d2e9ef1 + 632d4bb commit b91f5c2

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

src/main/kotlin/com/fasterxml/jackson/module/kotlin/Converters.kt

+12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
package com.fasterxml.jackson.module.kotlin
22

3+
import com.fasterxml.jackson.databind.JavaType
34
import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer
5+
import com.fasterxml.jackson.databind.type.TypeFactory
46
import com.fasterxml.jackson.databind.util.StdConverter
57
import kotlin.reflect.KClass
68

9+
internal class SequenceToIteratorConverter(private val input: JavaType) : StdConverter<Sequence<*>, Iterator<*>>() {
10+
override fun convert(value: Sequence<*>): Iterator<*> = value.iterator()
11+
12+
override fun getInputType(typeFactory: TypeFactory): JavaType = input
13+
// element-type may not be obtained, so a null check is required
14+
override fun getOutputType(typeFactory: TypeFactory): JavaType = input.containedType(0)
15+
?.let { typeFactory.constructCollectionLikeType(Iterator::class.java, it) }
16+
?: typeFactory.constructType(Iterator::class.java)
17+
}
18+
719
// S is nullable because value corresponds to a nullable value class
820
// @see KotlinNamesAnnotationIntrospector.findNullSerializer
921
internal class ValueClassBoxConverter<S : Any?, D : Any>(

src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinAnnotationIntrospector.kt

+8-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,14 @@ internal class KotlinAnnotationIntrospector(private val context: Module.SetupCon
6464
return super.findCreatorAnnotation(config, a)
6565
}
6666

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

7277
// Determine if the unbox result of value class is nullAable

src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinSerializers.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import java.lang.reflect.Method
1313
import java.lang.reflect.Modifier
1414
import java.math.BigInteger
1515

16+
@Deprecated(
17+
message = "This class will be removed in 2.16 or later as it has been replaced by SequenceToIteratorConverter.",
18+
replaceWith = ReplaceWith("com.fasterxml.jackson.module.kotlin.SequenceToIteratorConverter")
19+
)
1620
object SequenceSerializer : StdSerializer<Sequence<*>>(Sequence::class.java) {
1721
override fun serialize(value: Sequence<*>, gen: JsonGenerator, provider: SerializerProvider) {
1822
provider.defaultSerializeValue(value.iterator(), gen)
@@ -98,7 +102,6 @@ internal class KotlinSerializers : Serializers.Base() {
98102
val rawClass = type.rawClass
99103

100104
return when {
101-
Sequence::class.java.isAssignableFrom(rawClass) -> SequenceSerializer
102105
UByte::class.java.isAssignableFrom(rawClass) -> UByteSerializer
103106
UShort::class.java.isAssignableFrom(rawClass) -> UShortSerializer
104107
UInt::class.java.isAssignableFrom(rawClass) -> UIntSerializer

src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/SequenceSerdesTests.kt

+40-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.fasterxml.jackson.module.kotlin.test
22

3+
import com.fasterxml.jackson.core.JsonGenerator
4+
import com.fasterxml.jackson.databind.SerializerProvider
5+
import com.fasterxml.jackson.databind.annotation.JsonSerialize
6+
import com.fasterxml.jackson.databind.ser.std.StdSerializer
37
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
48
import com.fasterxml.jackson.module.kotlin.readValue
59
import org.junit.Test
@@ -42,4 +46,39 @@ class TestSequenceDeserializer {
4246
val result = objectMapper.writeValueAsString(data)
4347
assertEquals("{\"value\":[]}", result)
4448
}
45-
}
49+
50+
class ContentSer : StdSerializer<String>(String::class.java) {
51+
override fun serialize(value: String, gen: JsonGenerator, provider: SerializerProvider) {
52+
provider.defaultSerializeValue("$value-ser", gen)
53+
}
54+
}
55+
56+
data class ListWrapper(
57+
@JsonSerialize(contentUsing = ContentSer::class) val value: List<String>
58+
)
59+
60+
data class SequenceWrapper(
61+
@JsonSerialize(contentUsing = ContentSer::class)
62+
val value: Sequence<String>
63+
)
64+
65+
@Test
66+
fun contentUsingTest() {
67+
val mapper = jacksonObjectMapper()
68+
69+
val listResult = mapper.writeValueAsString(ListWrapper(listOf("foo")))
70+
val sequenceResult = mapper.writeValueAsString(SequenceWrapper(sequenceOf("foo")))
71+
72+
assertEquals("""{"value":["foo-ser"]}""", sequenceResult)
73+
assertEquals(listResult, sequenceResult)
74+
}
75+
76+
// @see #674
77+
@Test
78+
fun sequenceOfTest() {
79+
val mapper = jacksonObjectMapper()
80+
val result = mapper.writeValueAsString(sequenceOf("foo"))
81+
82+
assertEquals("""["foo"]""", result)
83+
}
84+
}

0 commit comments

Comments
 (0)