Prevent Kotlin Serialization converters side effects

This commit updates Kotlin serialization converters to perform
an additional check invoking
KotlinDetector#hasSerializableAnnotation to decide if the
related type should be processed or not.

The goal is to prevent in the default arrangement conflicts
between general purpose converters like Jackson and
Kotlin serialization when both are used.

New constructors allowing to specify a custom predicate
are also introduced.

See gh-35761
This commit is contained in:
Sébastien Deleuze
2025-11-07 18:59:33 +01:00
parent d0f57013b0
commit d64edc01c0
10 changed files with 421 additions and 90 deletions
@@ -33,6 +33,7 @@ import org.springframework.core.Ordered
import org.springframework.core.ResolvableType
import org.springframework.http.MediaType
import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter
import org.springframework.web.testfixture.http.MockHttpInputMessage
import org.springframework.web.testfixture.http.MockHttpOutputMessage
@@ -56,57 +57,107 @@ class KotlinSerializationCborHttpMessageConverterTests {
fraction = 42f
)
private val serializableBeanArray = arrayOf(serializableBean)
private val serializableBeanArrayBody = Cbor.Default.encodeToByteArray(serializableBeanArray)
private val serializableBeanArrayBody = Cbor.encodeToByteArray(serializableBeanArray)
@Test
fun canReadCbor() {
assertThat(converter.canRead(SerializableBean::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(String::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(String::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(NotSerializableBean::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(Map::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(Map::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Map<String, SerializableBean>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(List::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<SerializableBean>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(Set::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(Set::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Set<SerializableBean>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<ArrayList<Int>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<ArrayList<Int>>(), MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Ordered>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Ordered>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<Ordered>(), MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<Ordered>>(), MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<OrderedImpl>(), MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<OrderedImpl>>(), MediaType.APPLICATION_CBOR)).isFalse()
}
@Test
fun canReadCborWithAllTypes() {
val converterWithAllTypes = KotlinSerializationCborHttpMessageConverter { true }
assertThat(converterWithAllTypes.canRead(SerializableBean::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canRead(String::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(NotSerializableBean::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converterWithAllTypes.canRead(Map::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Map<String, SerializableBean>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<SerializableBean>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(Set::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Set<SerializableBean>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<ArrayList<Int>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Ordered>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Ordered>>(), MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<OrderedImpl>(), MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<OrderedImpl>>(), MediaType.APPLICATION_CBOR)).isFalse()
}
@Test
fun canWriteCbor() {
assertThat(converter.canWrite(SerializableBean::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(String::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(String::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(NotSerializableBean::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(Map::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(Map::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Map<String, SerializableBean>>(), Map::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(List::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<List<SerializableBean>>(), List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(Set::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(Set::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Set<SerializableBean>>(), Set::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<OrderedImpl>(), Ordered::class.java, MediaType.APPLICATION_CBOR)).isFalse()
}
@Test
fun canWriteCborWithAllTypes() {
val converterWithAllTypes = KotlinSerializationCborHttpMessageConverter { true }
assertThat(converterWithAllTypes.canWrite(SerializableBean::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canWrite(String::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(NotSerializableBean::class.java, MediaType.APPLICATION_CBOR)).isFalse()
assertThat(converterWithAllTypes.canWrite(Map::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Map<String, SerializableBean>>(), Map::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<SerializableBean>>(), List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(Set::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Set<SerializableBean>>(), Set::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_CBOR)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<OrderedImpl>(), Ordered::class.java, MediaType.APPLICATION_CBOR)).isFalse()
}
@Test
fun readObject() {
val serializableBeanBody = Cbor.Default.encodeToByteArray(serializableBean)
val serializableBeanBody = Cbor.encodeToByteArray(serializableBean)
val inputMessage = MockHttpInputMessage(serializableBeanBody)
inputMessage.headers.contentType = MediaType.APPLICATION_CBOR
val result = converter.read(SerializableBean::class.java, inputMessage) as SerializableBean
@@ -45,7 +45,6 @@ import kotlin.reflect.typeOf
* @author Andreas Ahlenstorf
* @author Sebastien Deleuze
*/
@Suppress("UsePropertyAccessSyntax")
class KotlinSerializationJsonHttpMessageConverterTests {
private val converter = KotlinSerializationJsonHttpMessageConverter()
@@ -54,22 +53,22 @@ class KotlinSerializationJsonHttpMessageConverterTests {
fun canReadJson() {
assertThat(converter.canRead(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(SerializableBean::class.java, MediaType.APPLICATION_PDF)).isFalse()
assertThat(converter.canRead(String::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(String::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(NotSerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(Map::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Map<String, SerializableBean>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(List::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<SerializableBean>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(Set::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Set<SerializableBean>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<ArrayList<Int>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<ArrayList<Int>>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_PDF)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Ordered>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Ordered>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<Ordered>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<Ordered>>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<OrderedImpl>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<OrderedImpl>>(), MediaType.APPLICATION_JSON)).isFalse()
@@ -78,25 +77,55 @@ class KotlinSerializationJsonHttpMessageConverterTests {
assertThat(converter.canRead(ResolvableType.forType(BigDecimal::class.java), MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun canReadJsonWithAllTypes() {
val converterWithAllTypes = KotlinSerializationJsonHttpMessageConverter { true }
assertThat(converterWithAllTypes.canRead(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(SerializableBean::class.java, MediaType.APPLICATION_PDF)).isFalse()
assertThat(converterWithAllTypes.canRead(String::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(NotSerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canRead(Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Map<String, SerializableBean>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<SerializableBean>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Set<SerializableBean>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<ArrayList<Int>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_PDF)).isFalse()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Ordered>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Ordered>>(), MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<OrderedImpl>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<OrderedImpl>>(), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canRead(ResolvableType.forType(ResolvableType.NONE.type), MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canRead(ResolvableType.forType(BigDecimal::class.java), MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun canWriteJson() {
assertThat(converter.canWrite(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(SerializableBean::class.java, MediaType.APPLICATION_PDF)).isFalse()
assertThat(converter.canWrite(String::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(String::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(NotSerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(Map::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Map<String, SerializableBean>>(), Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(List::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<List<SerializableBean>>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(Set::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Set<SerializableBean>>(), Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_PDF)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<OrderedImpl>(), OrderedImpl::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(ResolvableType.NONE, SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
@@ -104,6 +133,34 @@ class KotlinSerializationJsonHttpMessageConverterTests {
assertThat(converter.canWrite(ResolvableType.forType(BigDecimal::class.java), BigDecimal::class.java, MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun canWriteJsonWithAllTypes() {
val converterWithAllTypes = KotlinSerializationJsonHttpMessageConverter { true }
assertThat(converterWithAllTypes.canWrite(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(SerializableBean::class.java, MediaType.APPLICATION_PDF)).isFalse()
assertThat(converterWithAllTypes.canWrite(String::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(NotSerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canWrite(Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Map<String, SerializableBean>>(), Map::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<SerializableBean>>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Set<SerializableBean>>(), Set::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_PDF)).isFalse()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_JSON)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<OrderedImpl>(), OrderedImpl::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canWrite(ResolvableType.NONE, SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canWrite(ResolvableType.forType(BigDecimal::class.java), BigDecimal::class.java, MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun canReadMicroformats() {
val jsonSubtype = MediaType("application", "vnd.test-micro-type+json")
@@ -364,13 +421,13 @@ class KotlinSerializationJsonHttpMessageConverterTests {
@Test
fun canReadBigDecimalWithSerializerModule() {
val customConverter = KotlinSerializationJsonHttpMessageConverter(customJson)
val customConverter = KotlinSerializationJsonHttpMessageConverter(customJson) { true }
assertThat(customConverter.canRead(BigDecimal::class.java, MediaType.APPLICATION_JSON)).isTrue()
}
@Test
fun canWriteBigDecimalWithSerializerModule() {
val customConverter = KotlinSerializationJsonHttpMessageConverter(customJson)
val customConverter = KotlinSerializationJsonHttpMessageConverter(customJson) { true }
assertThat(customConverter.canWrite(BigDecimal::class.java, MediaType.APPLICATION_JSON)).isTrue()
}
@@ -27,6 +27,7 @@ import org.springframework.core.Ordered
import org.springframework.core.ResolvableType
import org.springframework.http.MediaType
import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.http.converter.cbor.KotlinSerializationCborHttpMessageConverter
import org.springframework.web.testfixture.http.MockHttpInputMessage
import org.springframework.web.testfixture.http.MockHttpOutputMessage
import java.lang.reflect.ParameterizedType
@@ -59,26 +60,27 @@ class KotlinSerializationProtobufHttpMessageConverterTests {
fraction = 42f
)
private val serializableBeanArray = arrayOf(serializableBean)
private val serializableBeanArrayBody = ProtoBuf.Default.encodeToByteArray(serializableBeanArray)
private val serializableBeanArrayBody = ProtoBuf.encodeToByteArray(serializableBeanArray)
@Test
fun canReadProtobuf() {
for (mimeType in mediaTypes) {
assertThat(converter.canRead(SerializableBean::class.java, mimeType)).isTrue()
assertThat(converter.canRead(String::class.java, mimeType)).isTrue()
assertThat(converter.canRead(String::class.java, mimeType)).isFalse()
assertThat(converter.canRead(NotSerializableBean::class.java, mimeType)).isFalse()
assertThat(converter.canRead(Map::class.java, mimeType)).isTrue()
assertThat(converter.canRead(Map::class.java, mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Map<String, SerializableBean>>(), mimeType)).isTrue()
assertThat(converter.canRead(List::class.java, mimeType)).isTrue()
assertThat(converter.canRead(List::class.java, mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<SerializableBean>>(), mimeType)).isTrue()
assertThat(converter.canRead(Set::class.java, mimeType)).isTrue()
assertThat(converter.canRead(Set::class.java, mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Set<SerializableBean>>(), mimeType)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), mimeType)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<ArrayList<Int>>(),mimeType)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<ArrayList<Int>>(),mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<Ordered>(), mimeType)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<List<Ordered>>(), mimeType)).isTrue()
assertThat(converter.canRead(resolvableTypeOf<Ordered>(), mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<Ordered>>(), mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<OrderedImpl>(), mimeType)).isFalse()
assertThat(converter.canRead(resolvableTypeOf<List<OrderedImpl>>(), mimeType)).isFalse()
}
@@ -86,31 +88,86 @@ class KotlinSerializationProtobufHttpMessageConverterTests {
assertThat(converter.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun canReadProtobufForAllTypes() {
val converterWithAllTypes = KotlinSerializationProtobufHttpMessageConverter { true }
for (mimeType in mediaTypes) {
assertThat(converterWithAllTypes.canRead(SerializableBean::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(String::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(NotSerializableBean::class.java, mimeType)).isFalse()
assertThat(converterWithAllTypes.canRead(Map::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Map<String, SerializableBean>>(), mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(List::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<SerializableBean>>(), mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(Set::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Set<SerializableBean>>(), mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Int>>(), mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<ArrayList<Int>>(),mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<Ordered>(), mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Ordered>>(), mimeType)).isTrue()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<OrderedImpl>(), mimeType)).isFalse()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<OrderedImpl>>(), mimeType)).isFalse()
}
assertThat(converterWithAllTypes.canRead(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canRead(resolvableTypeOf<List<Int>>(), MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun canWriteProtobuf() {
for (mimeType in mediaTypes) {
assertThat(converter.canWrite(SerializableBean::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(String::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(String::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(NotSerializableBean::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(Map::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(Map::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Map<String, SerializableBean>>(), Map::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(List::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(List::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<List<SerializableBean>>(), List::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(Set::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(Set::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Set<SerializableBean>>(), Set::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), OrderedImpl::class.java, mimeType)).isTrue()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, mimeType)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<Ordered>(), OrderedImpl::class.java, mimeType)).isFalse()
}
assertThat(converter.canWrite(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converter.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun canWriteProtobufForAllTypes() {
val converterWithAllTypes = KotlinSerializationProtobufHttpMessageConverter { true }
for (mimeType in mediaTypes) {
assertThat(converterWithAllTypes.canWrite(SerializableBean::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(String::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(NotSerializableBean::class.java, mimeType)).isFalse()
assertThat(converterWithAllTypes.canWrite(Map::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Map<String, SerializableBean>>(), Map::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(List::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<SerializableBean>>(), List::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(Set::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Set<SerializableBean>>(), Set::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<ArrayList<Int>>(), List::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Ordered>(), Ordered::class.java, mimeType)).isTrue()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<Ordered>(), OrderedImpl::class.java, mimeType)).isTrue()
}
assertThat(converterWithAllTypes.canWrite(SerializableBean::class.java, MediaType.APPLICATION_JSON)).isFalse()
assertThat(converterWithAllTypes.canWrite(resolvableTypeOf<List<Int>>(), List::class.java, MediaType.APPLICATION_JSON)).isFalse()
}
@Test
fun readObject() {
val serializableBeanBody = ProtoBuf.Default.encodeToByteArray(serializableBean)