Support CBOR and Protobuf with Kotlin Serialization

This commit introduces support for CBOR and Protobuf using Kotlin
serialization. Support comes in the form of Encoder/Decoder as well
as HttpMessageConverters. Seperate abstract base classes supply support
for binary and string (de)serialization.

The exising JSON codecs and message converters have been migrated to
use the new base classes.

Closes gh-27628
This commit is contained in:
Iain Henderson
2021-10-31 15:05:21 -04:00
committed by Arjen Poutsma
parent b6c2e8de23
commit b8243e6f84
40 changed files with 2398 additions and 415 deletions

View File

@@ -45,6 +45,7 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.ResourceRegionHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.cbor.KotlinSerializationCborHttpMessageConverter;
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
@@ -53,6 +54,7 @@ import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.protobuf.KotlinSerializationProtobufHttpMessageConverter;
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
@@ -211,8 +213,12 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
private static final boolean jsonbPresent;
private static final boolean kotlinSerializationCborPresent;
private static final boolean kotlinSerializationJsonPresent;
private static final boolean kotlinSerializationProtobufPresent;
static {
ClassLoader classLoader = WebMvcConfigurationSupport.class.getClassLoader();
romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
@@ -224,7 +230,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
jsonbPresent = ClassUtils.isPresent("jakarta.json.bind.Jsonb", classLoader);
kotlinSerializationCborPresent = ClassUtils.isPresent("kotlinx.serialization.cbor.Cbor", classLoader);
kotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);
kotlinSerializationProtobufPresent = ClassUtils.isPresent("kotlinx.serialization.protobuf.ProtoBuf", classLoader);
}
@@ -455,13 +463,13 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
if (!shouldIgnoreXml && (jaxb2Present || jackson2XmlPresent)) {
map.put("xml", MediaType.APPLICATION_XML);
}
if (jackson2Present || gsonPresent || jsonbPresent) {
if (jackson2Present || gsonPresent || jsonbPresent || kotlinSerializationJsonPresent) {
map.put("json", MediaType.APPLICATION_JSON);
}
if (jackson2SmilePresent) {
map.put("smile", MediaType.valueOf("application/x-jackson-smile"));
}
if (jackson2CborPresent) {
if (jackson2CborPresent || kotlinSerializationCborPresent) {
map.put("cbor", MediaType.APPLICATION_CBOR);
}
return map;
@@ -908,9 +916,16 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
}
}
if (kotlinSerializationCborPresent) {
messageConverters.add(new KotlinSerializationCborHttpMessageConverter());
}
if (kotlinSerializationJsonPresent) {
messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
}
if (kotlinSerializationProtobufPresent) {
messageConverters.add(new KotlinSerializationProtobufHttpMessageConverter());
}
if (jackson2Present) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {