Refine kotlinx.serialization support

This commit introduces the following changes:
 - Converters/codecs are now used based on generic type info.
 - On WebMvc and WebFlux, kotlinx.serialization is enabled along
   to Jackson because it only serializes Kotlin @Serializable classes
   which is not enough for error or actuator endpoints in Boot as
   described on spring-projects/spring-boot#24238.

TODO: leverage Kotlin/kotlinx.serialization#1164 when fixed.

Closes gh-26147
This commit is contained in:
Sébastien Deleuze
2020-11-26 12:15:23 +01:00
parent 1f701d9bad
commit 43faa439ab
13 changed files with 142 additions and 35 deletions

View File

@@ -53,6 +53,11 @@ class KotlinSerializationJsonDecoderTests : AbstractDecoderTests<KotlinSerializa
MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue()
Assertions.assertThat(decoder.canDecode(ResolvableType.forClass(Pojo::class.java),
MediaType("application", "json", StandardCharsets.ISO_8859_1))).isTrue()
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(List::class.java, Int::class.java), MediaType.APPLICATION_JSON)).isTrue()
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(List::class.java, Pojo::class.java), MediaType.APPLICATION_JSON)).isTrue()
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_JSON)).isTrue()
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_PDF)).isFalse()
}
@Test

View File

@@ -49,7 +49,11 @@ class KotlinSerializationJsonEncoderTests : AbstractEncoderTests<KotlinSerializa
MediaType("application", "json", StandardCharsets.UTF_8))).isTrue()
Assertions.assertThat(encoder.canEncode(ResolvableType.forClass(Pojo::class.java),
MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue()
Assertions.assertThat(encoder.canEncode(ResolvableType.NONE, null)).isTrue()
Assertions.assertThat(encoder.canEncode(ResolvableType.forClassWithGenerics(List::class.java, Int::class.java), MediaType.APPLICATION_JSON)).isTrue()
Assertions.assertThat(encoder.canEncode(ResolvableType.forClassWithGenerics(List::class.java, KotlinSerializationJsonDecoderTests.Pojo::class.java), MediaType.APPLICATION_JSON)).isTrue()
Assertions.assertThat(encoder.canEncode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_JSON)).isTrue()
Assertions.assertThat(encoder.canEncode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_PDF)).isFalse()
}
@Test

View File

@@ -24,6 +24,8 @@ import org.springframework.http.MediaType
import org.springframework.http.MockHttpInputMessage
import org.springframework.http.MockHttpOutputMessage
import org.springframework.http.converter.HttpMessageNotReadableException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.nio.charset.StandardCharsets
import kotlin.reflect.javaType
import kotlin.reflect.typeOf
@@ -34,6 +36,7 @@ import kotlin.reflect.typeOf
* @author Andreas Ahlenstorf
* @author Sebastien Deleuze
*/
@Suppress("UsePropertyAccessSyntax")
class KotlinSerializationJsonHttpMessageConverterTests {
private val converter = KotlinSerializationJsonHttpMessageConverter()
@@ -48,6 +51,11 @@ class KotlinSerializationJsonHttpMessageConverterTests {
assertThat(converter.canRead(Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(typeTokenOf<List<Int>>(), null, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(typeTokenOf<List<SerializableBean>>(), null, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(typeTokenOf<ArrayList<Int>>(), null, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(typeTokenOf<List<Int>>(), null, MediaType.APPLICATION_PDF)).isFalse()
}
@Test
@@ -60,6 +68,11 @@ class KotlinSerializationJsonHttpMessageConverterTests {
assertThat(converter.canWrite(Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(typeTokenOf<List<Int>>(), null, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(typeTokenOf<List<SerializableBean>>(), null, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(typeTokenOf<ArrayList<Int>>(), null, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(typeTokenOf<List<Int>>(), null, MediaType.APPLICATION_PDF)).isFalse()
}
@Test
@@ -296,4 +309,12 @@ class KotlinSerializationJsonHttpMessageConverterTests {
)
data class NotSerializableBean(val string: String)
open class TypeBase<T>
inline fun <reified T> typeTokenOf(): Type {
val base = object : TypeBase<T>() {}
val superType = base::class.java.genericSuperclass!!
return (superType as ParameterizedType).actualTypeArguments.first()!!
}
}