diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonDecoder.java index 58f582bb1e8..64e2d43ddb4 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonDecoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonDecoder.java @@ -21,6 +21,7 @@ import java.util.Map; import kotlinx.serialization.KSerializer; import kotlinx.serialization.SerializersKt; +import kotlinx.serialization.descriptors.PolymorphicKind; import kotlinx.serialization.json.Json; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; @@ -39,7 +40,9 @@ import org.springframework.util.MimeType; * Decode a byte stream into JSON and convert to Object's with * kotlinx.serialization. * - *

This decoder can be used to bind {@code @Serializable} Kotlin classes. + *

This decoder can be used to bind {@code @Serializable} Kotlin classes, + * open polymorphic serialization + * is not supported. * It supports {@code application/json} and {@code application/*+json} with * various character sets, {@code UTF-8} being the default. * @@ -132,6 +135,9 @@ public class KotlinSerializationJsonDecoder extends AbstractDecoder { KSerializer serializer = serializerCache.get(type); if (serializer == null) { serializer = SerializersKt.serializer(type); + if (serializer.getDescriptor().getKind().equals(PolymorphicKind.OPEN.INSTANCE)) { + throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet"); + } serializerCache.put(type, serializer); } return serializer; diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonEncoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonEncoder.java index cd577d4c828..3c30b2b0e00 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonEncoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonEncoder.java @@ -22,6 +22,7 @@ import java.util.Map; import kotlinx.serialization.KSerializer; import kotlinx.serialization.SerializersKt; +import kotlinx.serialization.descriptors.PolymorphicKind; import kotlinx.serialization.json.Json; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; @@ -42,7 +43,9 @@ import org.springframework.util.MimeType; * Encode from an {@code Object} stream to a byte stream of JSON objects using * kotlinx.serialization. * - *

This encoder can be used to bind {@code @Serializable} Kotlin classes. + *

This encoder can be used to bind {@code @Serializable} Kotlin classes, + * open polymorphic serialization + * is not supported. * It supports {@code application/json} and {@code application/*+json} with * various character sets, {@code UTF-8} being the default. * @@ -120,6 +123,9 @@ public class KotlinSerializationJsonEncoder extends AbstractEncoder { KSerializer serializer = serializerCache.get(type); if (serializer == null) { serializer = SerializersKt.serializer(type); + if (serializer.getDescriptor().getKind().equals(PolymorphicKind.OPEN.INSTANCE)) { + throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet"); + } serializerCache.put(type, serializer); } return serializer; diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java index 7149868217a..6025255e19e 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/KotlinSerializationJsonHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.util.Map; import kotlinx.serialization.KSerializer; import kotlinx.serialization.SerializationException; import kotlinx.serialization.SerializersKt; +import kotlinx.serialization.descriptors.PolymorphicKind; import kotlinx.serialization.json.Json; import org.springframework.core.GenericTypeResolver; @@ -43,7 +44,9 @@ import org.springframework.util.StreamUtils; * that can read and write JSON using * kotlinx.serialization. * - *

This converter can be used to bind {@code @Serializable} Kotlin classes. + *

This converter can be used to bind {@code @Serializable} Kotlin classes, + * open polymorphic serialization + * is not supported. * It supports {@code application/json} and {@code application/*+json} with * various character sets, {@code UTF-8} being the default. * @@ -182,6 +185,9 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric KSerializer serializer = serializerCache.get(type); if (serializer == null) { serializer = SerializersKt.serializer(type); + if (serializer.getDescriptor().getKind().equals(PolymorphicKind.OPEN.INSTANCE)) { + throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet"); + } serializerCache.put(type, serializer); } return serializer; diff --git a/spring-web/src/test/kotlin/org/springframework/http/codec/json/KotlinSerializationJsonDecoderTests.kt b/spring-web/src/test/kotlin/org/springframework/http/codec/json/KotlinSerializationJsonDecoderTests.kt index f1489814db1..d333bd0a86b 100644 --- a/spring-web/src/test/kotlin/org/springframework/http/codec/json/KotlinSerializationJsonDecoderTests.kt +++ b/spring-web/src/test/kotlin/org/springframework/http/codec/json/KotlinSerializationJsonDecoderTests.kt @@ -19,6 +19,7 @@ package org.springframework.http.codec.json import kotlinx.serialization.Serializable import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test +import org.springframework.core.Ordered import org.springframework.core.ResolvableType import org.springframework.core.io.buffer.DataBuffer import org.springframework.core.testfixture.codec.AbstractDecoderTests @@ -58,6 +59,7 @@ class KotlinSerializationJsonDecoderTests : AbstractDecoderTests>(), Map::class.java, MediaType.APPLICATION_JSON)).isTrue() + assertThat(converter.canRead(List::class.java, MediaType.APPLICATION_JSON)).isFalse() + assertThat(converter.canRead(typeTokenOf>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue() + assertThat(converter.canRead(Set::class.java, MediaType.APPLICATION_JSON)).isFalse() + assertThat(converter.canRead(typeTokenOf>(), Set::class.java, MediaType.APPLICATION_JSON)).isTrue() - assertThat(converter.canRead(typeTokenOf>(), null, MediaType.APPLICATION_JSON)).isTrue() - assertThat(converter.canRead(typeTokenOf>(), null, MediaType.APPLICATION_JSON)).isTrue() - assertThat(converter.canRead(typeTokenOf>(), null, MediaType.APPLICATION_JSON)).isTrue() - assertThat(converter.canRead(typeTokenOf>(), null, MediaType.APPLICATION_PDF)).isFalse() + assertThat(converter.canRead(typeTokenOf>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue() + assertThat(converter.canRead(typeTokenOf>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue() + assertThat(converter.canRead(typeTokenOf>(), List::class.java, MediaType.APPLICATION_PDF)).isFalse() + + assertThat(converter.canRead(typeTokenOf(), Ordered::class.java, MediaType.APPLICATION_JSON)).isFalse() } @Test @@ -65,14 +70,18 @@ class KotlinSerializationJsonHttpMessageConverterTests { assertThat(converter.canWrite(String::class.java, MediaType.APPLICATION_JSON)).isTrue() assertThat(converter.canWrite(NotSerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse() - 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(Map::class.java, MediaType.APPLICATION_JSON)).isFalse() + assertThat(converter.canWrite(typeTokenOf>(), Map::class.java, MediaType.APPLICATION_JSON)).isTrue() + assertThat(converter.canWrite(List::class.java, MediaType.APPLICATION_JSON)).isFalse() + assertThat(converter.canWrite(typeTokenOf>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue() + assertThat(converter.canWrite(Set::class.java, MediaType.APPLICATION_JSON)).isFalse() + assertThat(converter.canWrite(typeTokenOf>(), Set::class.java, MediaType.APPLICATION_JSON)).isTrue() assertThat(converter.canWrite(typeTokenOf>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue() - assertThat(converter.canWrite(typeTokenOf>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue() assertThat(converter.canWrite(typeTokenOf>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue() assertThat(converter.canWrite(typeTokenOf>(), List::class.java, MediaType.APPLICATION_PDF)).isFalse() + + assertThat(converter.canWrite(typeTokenOf(), Ordered::class.java, MediaType.APPLICATION_JSON)).isFalse() } @Test