Skip to content

Commit 0844f74

Browse files
committed
Merge branch '2.15' into 2.16
2 parents b48acb4 + 3a906e3 commit 0844f74

File tree

6 files changed

+74
-6
lines changed

6 files changed

+74
-6
lines changed

release-notes/CREDITS-2.x

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ Authors:
1515

1616
Contributors:
1717

18+
# 2.15.2
19+
20+
WrongWrong (@k163377)
21+
* #675: Modified to use Converter in Sequence serialization
22+
1823
# 2.15.0
1924

2025
Ilya Ryzhenkov (@orangy)

release-notes/VERSION-2.x

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ Co-maintainers:
1818

1919
2.16.0 (not yet relesed)
2020

21-
No changes since 2.15
21+
2.15.2 (not yet relesed)
22+
23+
#675: Modified to use Converter in Sequence serialization
24+
This change allows serialization-related annotations, such as `JsonSerialize(contentUsing = ...)`, to work on `Sequence`.
25+
Also fixes #674.
2226

2327
2.15.1 (16-May-2023)
2428

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

Lines changed: 12 additions & 0 deletions
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

Lines changed: 8 additions & 3 deletions
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

Lines changed: 4 additions & 1 deletion
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

Lines changed: 40 additions & 1 deletion
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)