Prevent kotlinx.serialization usage on collection of interfaces
Closes gh-26371
This commit is contained in:
parent
0fc8bf654b
commit
9c6b1b645d
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,11 +17,14 @@
|
||||||
package org.springframework.http.codec.json;
|
package org.springframework.http.codec.json;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer;
|
import kotlinx.serialization.KSerializer;
|
||||||
import kotlinx.serialization.SerializersKt;
|
import kotlinx.serialization.SerializersKt;
|
||||||
import kotlinx.serialization.descriptors.PolymorphicKind;
|
import kotlinx.serialization.descriptors.PolymorphicKind;
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor;
|
||||||
import kotlinx.serialization.json.Json;
|
import kotlinx.serialization.json.Json;
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
@ -135,7 +138,7 @@ public class KotlinSerializationJsonDecoder extends AbstractDecoder<Object> {
|
||||||
KSerializer<Object> serializer = serializerCache.get(type);
|
KSerializer<Object> serializer = serializerCache.get(type);
|
||||||
if (serializer == null) {
|
if (serializer == null) {
|
||||||
serializer = SerializersKt.serializer(type);
|
serializer = SerializersKt.serializer(type);
|
||||||
if (serializer.getDescriptor().getKind().equals(PolymorphicKind.OPEN.INSTANCE)) {
|
if (hasPolymorphism(serializer.getDescriptor(), new HashSet<>())) {
|
||||||
throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet");
|
throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet");
|
||||||
}
|
}
|
||||||
serializerCache.put(type, serializer);
|
serializerCache.put(type, serializer);
|
||||||
|
|
@ -143,4 +146,18 @@ public class KotlinSerializationJsonDecoder extends AbstractDecoder<Object> {
|
||||||
return serializer;
|
return serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasPolymorphism(SerialDescriptor descriptor, Set<String> alreadyProcessed) {
|
||||||
|
alreadyProcessed.add(descriptor.getSerialName());
|
||||||
|
if (descriptor.getKind().equals(PolymorphicKind.OPEN.INSTANCE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0 ; i < descriptor.getElementsCount() ; i++) {
|
||||||
|
SerialDescriptor elementDescriptor = descriptor.getElementDescriptor(i);
|
||||||
|
if (!alreadyProcessed.contains(elementDescriptor.getSerialName()) && hasPolymorphism(elementDescriptor, alreadyProcessed)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,12 +17,15 @@
|
||||||
package org.springframework.http.codec.json;
|
package org.springframework.http.codec.json;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer;
|
import kotlinx.serialization.KSerializer;
|
||||||
import kotlinx.serialization.SerializersKt;
|
import kotlinx.serialization.SerializersKt;
|
||||||
import kotlinx.serialization.descriptors.PolymorphicKind;
|
import kotlinx.serialization.descriptors.PolymorphicKind;
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor;
|
||||||
import kotlinx.serialization.json.Json;
|
import kotlinx.serialization.json.Json;
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
@ -123,7 +126,7 @@ public class KotlinSerializationJsonEncoder extends AbstractEncoder<Object> {
|
||||||
KSerializer<Object> serializer = serializerCache.get(type);
|
KSerializer<Object> serializer = serializerCache.get(type);
|
||||||
if (serializer == null) {
|
if (serializer == null) {
|
||||||
serializer = SerializersKt.serializer(type);
|
serializer = SerializersKt.serializer(type);
|
||||||
if (serializer.getDescriptor().getKind().equals(PolymorphicKind.OPEN.INSTANCE)) {
|
if (hasPolymorphism(serializer.getDescriptor(), new HashSet<>())) {
|
||||||
throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet");
|
throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet");
|
||||||
}
|
}
|
||||||
serializerCache.put(type, serializer);
|
serializerCache.put(type, serializer);
|
||||||
|
|
@ -131,4 +134,18 @@ public class KotlinSerializationJsonEncoder extends AbstractEncoder<Object> {
|
||||||
return serializer;
|
return serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasPolymorphism(SerialDescriptor descriptor, Set<String> alreadyProcessed) {
|
||||||
|
alreadyProcessed.add(descriptor.getSerialName());
|
||||||
|
if (descriptor.getKind().equals(PolymorphicKind.OPEN.INSTANCE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0 ; i < descriptor.getElementsCount() ; i++) {
|
||||||
|
SerialDescriptor elementDescriptor = descriptor.getElementDescriptor(i);
|
||||||
|
if (!alreadyProcessed.contains(elementDescriptor.getSerialName()) && hasPolymorphism(elementDescriptor, alreadyProcessed)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,15 @@ import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer;
|
import kotlinx.serialization.KSerializer;
|
||||||
import kotlinx.serialization.SerializationException;
|
import kotlinx.serialization.SerializationException;
|
||||||
import kotlinx.serialization.SerializersKt;
|
import kotlinx.serialization.SerializersKt;
|
||||||
import kotlinx.serialization.descriptors.PolymorphicKind;
|
import kotlinx.serialization.descriptors.PolymorphicKind;
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor;
|
||||||
import kotlinx.serialization.json.Json;
|
import kotlinx.serialization.json.Json;
|
||||||
|
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
|
|
@ -185,7 +188,7 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
|
||||||
KSerializer<Object> serializer = serializerCache.get(type);
|
KSerializer<Object> serializer = serializerCache.get(type);
|
||||||
if (serializer == null) {
|
if (serializer == null) {
|
||||||
serializer = SerializersKt.serializer(type);
|
serializer = SerializersKt.serializer(type);
|
||||||
if (serializer.getDescriptor().getKind().equals(PolymorphicKind.OPEN.INSTANCE)) {
|
if (hasPolymorphism(serializer.getDescriptor(), new HashSet<>())) {
|
||||||
throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet");
|
throw new UnsupportedOperationException("Open polymorphic serialization is not supported yet");
|
||||||
}
|
}
|
||||||
serializerCache.put(type, serializer);
|
serializerCache.put(type, serializer);
|
||||||
|
|
@ -193,4 +196,18 @@ public class KotlinSerializationJsonHttpMessageConverter extends AbstractGeneric
|
||||||
return serializer;
|
return serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasPolymorphism(SerialDescriptor descriptor, Set<String> alreadyProcessed) {
|
||||||
|
alreadyProcessed.add(descriptor.getSerialName());
|
||||||
|
if (descriptor.getKind().equals(PolymorphicKind.OPEN.INSTANCE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0 ; i < descriptor.getElementsCount() ; i++) {
|
||||||
|
SerialDescriptor elementDescriptor = descriptor.getElementDescriptor(i);
|
||||||
|
if (!alreadyProcessed.contains(elementDescriptor.getSerialName()) && hasPolymorphism(elementDescriptor, alreadyProcessed)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -56,6 +56,7 @@ class KotlinSerializationJsonDecoderTests : AbstractDecoderTests<KotlinSerializa
|
||||||
MediaType("application", "json", StandardCharsets.ISO_8859_1))).isTrue()
|
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, Int::class.java), MediaType.APPLICATION_JSON)).isTrue()
|
||||||
|
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(List::class.java, Ordered::class.java), MediaType.APPLICATION_JSON)).isFalse()
|
||||||
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(List::class.java, Pojo::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_JSON)).isTrue()
|
||||||
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_PDF)).isFalse()
|
Assertions.assertThat(decoder.canDecode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_PDF)).isFalse()
|
||||||
|
|
@ -101,6 +102,6 @@ class KotlinSerializationJsonDecoderTests : AbstractDecoderTests<KotlinSerializa
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Pojo(val foo: String, val bar: String)
|
data class Pojo(val foo: String, val bar: String, val pojo: Pojo? = null)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -52,7 +52,8 @@ class KotlinSerializationJsonEncoderTests : AbstractEncoderTests<KotlinSerializa
|
||||||
MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue()
|
MediaType("application", "json", StandardCharsets.US_ASCII))).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, 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(List::class.java, Ordered::class.java), MediaType.APPLICATION_JSON)).isFalse()
|
||||||
|
Assertions.assertThat(encoder.canEncode(ResolvableType.forClassWithGenerics(List::class.java, 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_JSON)).isTrue()
|
||||||
Assertions.assertThat(encoder.canEncode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_PDF)).isFalse()
|
Assertions.assertThat(encoder.canEncode(ResolvableType.forClassWithGenerics(ArrayList::class.java, Int::class.java), MediaType.APPLICATION_PDF)).isFalse()
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +98,6 @@ class KotlinSerializationJsonEncoderTests : AbstractEncoderTests<KotlinSerializa
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Pojo(val foo: String, val bar: String)
|
data class Pojo(val foo: String, val bar: String, val pojo: Pojo? = null)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -61,6 +61,7 @@ class KotlinSerializationJsonHttpMessageConverterTests {
|
||||||
assertThat(converter.canRead(typeTokenOf<List<Int>>(), List::class.java, MediaType.APPLICATION_PDF)).isFalse()
|
assertThat(converter.canRead(typeTokenOf<List<Int>>(), List::class.java, MediaType.APPLICATION_PDF)).isFalse()
|
||||||
|
|
||||||
assertThat(converter.canRead(typeTokenOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_JSON)).isFalse()
|
assertThat(converter.canRead(typeTokenOf<Ordered>(), Ordered::class.java, MediaType.APPLICATION_JSON)).isFalse()
|
||||||
|
assertThat(converter.canRead(typeTokenOf<List<Ordered>>(), List::class.java, MediaType.APPLICATION_JSON)).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -315,7 +316,8 @@ class KotlinSerializationJsonHttpMessageConverterTests {
|
||||||
val number: Int,
|
val number: Int,
|
||||||
val string: String?,
|
val string: String?,
|
||||||
val bool: Boolean,
|
val bool: Boolean,
|
||||||
val fraction: Float
|
val fraction: Float,
|
||||||
|
val serializableBean: SerializableBean? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
data class NotSerializableBean(val string: String)
|
data class NotSerializableBean(val string: String)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue