diff --git a/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java b/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java index 5b273b14d29..66bd4e9b79f 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java +++ b/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java @@ -104,33 +104,35 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { boolean registerDefaults; - @Nullable ByteArrayHttpMessageConverter byteArrayMessageConverter; + @Nullable ByteArrayHttpMessageConverter byteArrayConverter; - @Nullable HttpMessageConverter stringMessageConverter; + @Nullable HttpMessageConverter stringConverter; - @Nullable HttpMessageConverter resourceMessageConverter; + @Nullable HttpMessageConverter resourceConverter; - @Nullable HttpMessageConverter resourceRegionMessageConverter; + @Nullable HttpMessageConverter resourceRegionConverter; @Nullable Consumer> configurer; - @Nullable HttpMessageConverter jsonMessageConverter; + @Nullable HttpMessageConverter kotlinJsonConverter; - @Nullable HttpMessageConverter xmlMessageConverter; + @Nullable HttpMessageConverter jsonConverter; - @Nullable HttpMessageConverter smileMessageConverter; + @Nullable HttpMessageConverter xmlConverter; - @Nullable HttpMessageConverter cborMessageConverter; + @Nullable HttpMessageConverter smileConverter; - @Nullable HttpMessageConverter yamlMessageConverter; + @Nullable HttpMessageConverter cborConverter; - @Nullable HttpMessageConverter protobufMessageConverter; + @Nullable HttpMessageConverter yamlConverter; - @Nullable HttpMessageConverter atomMessageConverter; + @Nullable HttpMessageConverter protobufConverter; - @Nullable HttpMessageConverter rssMessageConverter; + @Nullable HttpMessageConverter atomConverter; - final List> customMessageConverters = new ArrayList<>(); + @Nullable HttpMessageConverter rssConverter; + + final List> customConverters = new ArrayList<>(); static { @@ -156,45 +158,50 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { } - void setStringMessageConverter(HttpMessageConverter stringMessageConverter) { - Assert.isTrue(stringMessageConverter.getSupportedMediaTypes().contains(MediaType.TEXT_PLAIN), - "stringMessageConverter should support 'text/plain'"); - this.stringMessageConverter = stringMessageConverter; + void setStringConverter(HttpMessageConverter stringConverter) { + Assert.isTrue(stringConverter.getSupportedMediaTypes().contains(MediaType.TEXT_PLAIN), + "stringConverter should support 'text/plain'"); + this.stringConverter = stringConverter; } - void setJsonMessageConverter(HttpMessageConverter jsonMessageConverter) { - Assert.isTrue(jsonMessageConverter.getSupportedMediaTypes().contains(MediaType.APPLICATION_JSON), - "jsonMessageConverter should support 'application/json'"); - this.jsonMessageConverter = jsonMessageConverter; + void setKotlinSerializationJsonConverter(HttpMessageConverter kotlinJsonConverter) { + Assert.notNull(kotlinJsonConverter, "kotlinJsonConverter must not be null"); + this.kotlinJsonConverter = kotlinJsonConverter; } - void setXmlMessageConverter(HttpMessageConverter xmlMessageConverter) { - Assert.isTrue(xmlMessageConverter.getSupportedMediaTypes().contains(MediaType.TEXT_XML), - "xmlMessageConverter should support 'text/xml'"); - this.xmlMessageConverter = xmlMessageConverter; + void setJsonConverter(HttpMessageConverter jsonConverter) { + Assert.isTrue(jsonConverter.getSupportedMediaTypes().contains(MediaType.APPLICATION_JSON), + "jsonConverter should support 'application/json'"); + this.jsonConverter = jsonConverter; } - void setSmileMessageConverter(HttpMessageConverter smileMessageConverter) { - Assert.isTrue(smileMessageConverter.getSupportedMediaTypes().contains(new MediaType("application", "x-jackson-smile")), - "smileMessageConverter should support 'application/x-jackson-smile'"); - this.smileMessageConverter = smileMessageConverter; + void setXmlConverter(HttpMessageConverter xmlConverter) { + Assert.isTrue(xmlConverter.getSupportedMediaTypes().contains(MediaType.TEXT_XML), + "xmlConverter should support 'text/xml'"); + this.xmlConverter = xmlConverter; } - void setCborMessageConverter(HttpMessageConverter cborMessageConverter) { - Assert.isTrue(cborMessageConverter.getSupportedMediaTypes().contains(MediaType.APPLICATION_CBOR), - "cborMessageConverter should support 'application/cbor'"); - this.cborMessageConverter = cborMessageConverter; + void setSmileConverter(HttpMessageConverter smileConverter) { + Assert.isTrue(smileConverter.getSupportedMediaTypes().contains(new MediaType("application", "x-jackson-smile")), + "smileConverter should support 'application/x-jackson-smile'"); + this.smileConverter = smileConverter; } - void setYamlMessageConverter(HttpMessageConverter yamlMessageConverter) { - Assert.isTrue(yamlMessageConverter.getSupportedMediaTypes().contains(MediaType.APPLICATION_YAML), - "yamlMessageConverter should support 'application/yaml'"); - this.yamlMessageConverter = yamlMessageConverter; + void setCborConverter(HttpMessageConverter cborConverter) { + Assert.isTrue(cborConverter.getSupportedMediaTypes().contains(MediaType.APPLICATION_CBOR), + "cborConverter should support 'application/cbor'"); + this.cborConverter = cborConverter; + } + + void setYamlConverter(HttpMessageConverter yamlConverter) { + Assert.isTrue(yamlConverter.getSupportedMediaTypes().contains(MediaType.APPLICATION_YAML), + "yamlConverter should support 'application/yaml'"); + this.yamlConverter = yamlConverter; } void addCustomMessageConverter(HttpMessageConverter customConverter) { Assert.notNull(customConverter, "'customConverter' must not be null"); - this.customMessageConverters.add(customConverter); + this.customConverters.add(customConverter); } void addMessageConverterConfigurer(Consumer> configurer) { @@ -203,126 +210,131 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { List> getBaseConverters() { List> converters = new ArrayList<>(); - if (this.byteArrayMessageConverter != null) { - converters.add(this.byteArrayMessageConverter); + if (this.byteArrayConverter != null) { + converters.add(this.byteArrayConverter); } - if (this.stringMessageConverter != null) { - converters.add(this.stringMessageConverter); + if (this.stringConverter != null) { + converters.add(this.stringConverter); } return converters; } List> getCoreConverters() { List> converters = new ArrayList<>(); - if (this.jsonMessageConverter != null) { - converters.add(this.jsonMessageConverter); + if (this.kotlinJsonConverter != null) { + converters.add(this.kotlinJsonConverter); } - if (this.smileMessageConverter != null) { - converters.add(this.smileMessageConverter); + if (this.jsonConverter != null) { + converters.add(this.jsonConverter); } - if (this.cborMessageConverter!= null) { - converters.add(this.cborMessageConverter); + if (this.smileConverter != null) { + converters.add(this.smileConverter); } - if (this.yamlMessageConverter!= null) { - converters.add(this.yamlMessageConverter); + if (this.cborConverter != null) { + converters.add(this.cborConverter); } - if (this.xmlMessageConverter!= null) { - converters.add(this.xmlMessageConverter); + if (this.yamlConverter != null) { + converters.add(this.yamlConverter); } - if (this.protobufMessageConverter != null) { - converters.add(this.protobufMessageConverter); + if (this.xmlConverter != null) { + converters.add(this.xmlConverter); } - if (this.atomMessageConverter != null) { - converters.add(this.atomMessageConverter); + if (this.protobufConverter != null) { + converters.add(this.protobufConverter); } - if (this.rssMessageConverter != null) { - converters.add(this.rssMessageConverter); + if (this.atomConverter != null) { + converters.add(this.atomConverter); + } + if (this.rssConverter != null) { + converters.add(this.rssConverter); } return converters; } List> getCustomConverters() { - return this.customMessageConverters; + return this.customConverters; } void detectMessageConverters() { - this.byteArrayMessageConverter = new ByteArrayHttpMessageConverter(); + this.byteArrayConverter = new ByteArrayHttpMessageConverter(); - if (this.stringMessageConverter == null) { - this.stringMessageConverter = new StringHttpMessageConverter(); + if (this.stringConverter == null) { + this.stringConverter = new StringHttpMessageConverter(); } - if (this.jsonMessageConverter == null) { + if (this.kotlinJsonConverter == null) { + if (KOTLIN_SERIALIZATION_JSON_PRESENT) { + this.kotlinJsonConverter = new KotlinSerializationJsonHttpMessageConverter(); + } + } + if (this.jsonConverter == null) { if (JACKSON_PRESENT) { - this.jsonMessageConverter = new JacksonJsonHttpMessageConverter(); + this.jsonConverter = new JacksonJsonHttpMessageConverter(); } else if (JACKSON_2_PRESENT) { - this.jsonMessageConverter = new MappingJackson2HttpMessageConverter(); + this.jsonConverter = new MappingJackson2HttpMessageConverter(); } else if (GSON_PRESENT) { - this.jsonMessageConverter = new GsonHttpMessageConverter(); + this.jsonConverter = new GsonHttpMessageConverter(); } else if (JSONB_PRESENT) { - this.jsonMessageConverter = new JsonbHttpMessageConverter(); - } - else if (KOTLIN_SERIALIZATION_JSON_PRESENT) { - this.jsonMessageConverter = new KotlinSerializationJsonHttpMessageConverter(); + this.jsonConverter = new JsonbHttpMessageConverter(); } } - if (this.xmlMessageConverter == null) { + if (this.xmlConverter == null) { if (JACKSON_XML_PRESENT) { - this.xmlMessageConverter = new JacksonXmlHttpMessageConverter(); + this.xmlConverter = new JacksonXmlHttpMessageConverter(); } else if (JACKSON_2_XML_PRESENT) { - this.xmlMessageConverter = new MappingJackson2XmlHttpMessageConverter(); + this.xmlConverter = new MappingJackson2XmlHttpMessageConverter(); } else if (JAXB_2_PRESENT) { - this.xmlMessageConverter = new Jaxb2RootElementHttpMessageConverter(); + this.xmlConverter = new Jaxb2RootElementHttpMessageConverter(); } } - if (this.smileMessageConverter == null) { + if (this.smileConverter == null) { if (JACKSON_SMILE_PRESENT) { - this.smileMessageConverter = new JacksonSmileHttpMessageConverter(); + this.smileConverter = new JacksonSmileHttpMessageConverter(); } else if (JACKSON_2_SMILE_PRESENT) { - this.smileMessageConverter = new MappingJackson2SmileHttpMessageConverter(); + this.smileConverter = new MappingJackson2SmileHttpMessageConverter(); } } - if (this.cborMessageConverter == null) { + if (this.cborConverter == null) { if (JACKSON_CBOR_PRESENT) { - this.cborMessageConverter = new JacksonCborHttpMessageConverter(); + this.cborConverter = new JacksonCborHttpMessageConverter(); } else if (JACKSON_2_CBOR_PRESENT) { - this.cborMessageConverter = new MappingJackson2CborHttpMessageConverter(); + this.cborConverter = new MappingJackson2CborHttpMessageConverter(); } else if (KOTLIN_SERIALIZATION_CBOR_PRESENT) { - this.cborMessageConverter = new KotlinSerializationCborHttpMessageConverter(); + this.cborConverter = new KotlinSerializationCborHttpMessageConverter(); } } - if (this.yamlMessageConverter == null) { + if (this.yamlConverter == null) { if (JACKSON_YAML_PRESENT) { - this.yamlMessageConverter = new JacksonYamlHttpMessageConverter(); + this.yamlConverter = new JacksonYamlHttpMessageConverter(); } else if (JACKSON_2_YAML_PRESENT) { - this.yamlMessageConverter = new MappingJackson2YamlHttpMessageConverter(); + this.yamlConverter = new MappingJackson2YamlHttpMessageConverter(); } } - if (this.protobufMessageConverter == null) { + if (this.protobufConverter == null) { if (KOTLIN_SERIALIZATION_PROTOBUF_PRESENT) { - this.protobufMessageConverter = new KotlinSerializationProtobufHttpMessageConverter(); + this.protobufConverter = new KotlinSerializationProtobufHttpMessageConverter(); } } if (ROME_PRESENT) { - if (this.atomMessageConverter == null) { - this.atomMessageConverter = new AtomFeedHttpMessageConverter(); + if (this.atomConverter == null) { + this.atomConverter = new AtomFeedHttpMessageConverter(); } - if (this.rssMessageConverter == null) { - this.rssMessageConverter = new RssChannelHttpMessageConverter(); + if (this.rssConverter == null) { + this.rssConverter = new RssChannelHttpMessageConverter(); } } } @@ -338,38 +350,44 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { } @Override - public ClientBuilder withStringConverter(HttpMessageConverter stringMessageConverter) { - setStringMessageConverter(stringMessageConverter); + public ClientBuilder withStringConverter(HttpMessageConverter stringConverter) { + setStringConverter(stringConverter); return this; } @Override - public ClientBuilder withJsonConverter(HttpMessageConverter jsonMessageConverter) { - setJsonMessageConverter(jsonMessageConverter); + public ClientBuilder withKotlinSerializationJsonConverter(HttpMessageConverter kotlinSerializationJsonConverter) { + setKotlinSerializationJsonConverter(kotlinSerializationJsonConverter); return this; } @Override - public ClientBuilder withXmlConverter(HttpMessageConverter xmlMessageConverter) { - setXmlMessageConverter(xmlMessageConverter); + public ClientBuilder withJsonConverter(HttpMessageConverter jsonConverter) { + setJsonConverter(jsonConverter); return this; } @Override - public ClientBuilder withSmileConverter(HttpMessageConverter smileMessageConverter) { - setSmileMessageConverter(smileMessageConverter); + public ClientBuilder withXmlConverter(HttpMessageConverter xmlConverter) { + setXmlConverter(xmlConverter); return this; } @Override - public ClientBuilder withCborConverter(HttpMessageConverter cborMessageConverter) { - setCborMessageConverter(cborMessageConverter); + public ClientBuilder withSmileConverter(HttpMessageConverter smileConverter) { + setSmileConverter(smileConverter); return this; } @Override - public ClientBuilder withYamlConverter(HttpMessageConverter yamlMessageConverter) { - setYamlMessageConverter(yamlMessageConverter); + public ClientBuilder withCborConverter(HttpMessageConverter cborConverter) { + setCborConverter(cborConverter); + return this; + } + + @Override + public ClientBuilder withYamlConverter(HttpMessageConverter yamlConverter) { + setYamlConverter(yamlConverter); return this; } @@ -388,7 +406,7 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @Override public HttpMessageConverters build() { if (this.registerDefaults) { - this.resourceMessageConverter = new ResourceHttpMessageConverter(false); + this.resourceConverter = new ResourceHttpMessageConverter(false); detectMessageConverters(); } List> partConverters = new ArrayList<>(this.getCustomConverters()); @@ -396,8 +414,8 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { if (this.registerDefaults) { partConverters.addAll(this.getCoreConverters()); allConverters.addAll(this.getBaseConverters()); - if (this.resourceMessageConverter != null) { - allConverters.add(this.resourceMessageConverter); + if (this.resourceConverter != null) { + allConverters.add(this.resourceConverter); } } if (!partConverters.isEmpty() || !allConverters.isEmpty()) { @@ -423,38 +441,44 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { } @Override - public ServerBuilder withStringConverter(HttpMessageConverter stringMessageConverter) { - setStringMessageConverter(stringMessageConverter); + public ServerBuilder withStringConverter(HttpMessageConverter stringConverter) { + setStringConverter(stringConverter); return this; } @Override - public ServerBuilder withJsonConverter(HttpMessageConverter jsonMessageConverter) { - setJsonMessageConverter(jsonMessageConverter); + public ServerBuilder withKotlinSerializationJsonConverter(HttpMessageConverter kotlinSerializationJsonConverter) { + setKotlinSerializationJsonConverter(kotlinSerializationJsonConverter); return this; } @Override - public ServerBuilder withXmlConverter(HttpMessageConverter xmlMessageConverter) { - setXmlMessageConverter(xmlMessageConverter); + public ServerBuilder withJsonConverter(HttpMessageConverter jsonConverter) { + setJsonConverter(jsonConverter); return this; } @Override - public ServerBuilder withSmileConverter(HttpMessageConverter smileMessageConverter) { - setSmileMessageConverter(smileMessageConverter); + public ServerBuilder withXmlConverter(HttpMessageConverter xmlConverter) { + setXmlConverter(xmlConverter); return this; } @Override - public ServerBuilder withCborConverter(HttpMessageConverter cborMessageConverter) { - setCborMessageConverter(cborMessageConverter); + public ServerBuilder withSmileConverter(HttpMessageConverter smileConverter) { + setSmileConverter(smileConverter); return this; } @Override - public ServerBuilder withYamlConverter(HttpMessageConverter yamlMessageConverter) { - setYamlMessageConverter(yamlMessageConverter); + public ServerBuilder withCborConverter(HttpMessageConverter cborConverter) { + setCborConverter(cborConverter); + return this; + } + + @Override + public ServerBuilder withYamlConverter(HttpMessageConverter yamlConverter) { + setYamlConverter(yamlConverter); return this; } @@ -473,8 +497,8 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @Override public HttpMessageConverters build() { if (this.registerDefaults) { - this.resourceMessageConverter = new ResourceHttpMessageConverter(); - this.resourceRegionMessageConverter = new ResourceRegionHttpMessageConverter(); + this.resourceConverter = new ResourceHttpMessageConverter(); + this.resourceRegionConverter = new ResourceRegionHttpMessageConverter(); detectMessageConverters(); } List> partConverters = new ArrayList<>(this.getCustomConverters()); @@ -482,11 +506,11 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { if (this.registerDefaults) { partConverters.addAll(this.getCoreConverters()); allConverters.addAll(this.getBaseConverters()); - if (this.resourceMessageConverter != null) { - allConverters.add(this.resourceMessageConverter); + if (this.resourceConverter != null) { + allConverters.add(this.resourceConverter); } - if (this.resourceRegionMessageConverter != null) { - allConverters.add(this.resourceRegionMessageConverter); + if (this.resourceRegionConverter != null) { + allConverters.add(this.resourceRegionConverter); } } if (!partConverters.isEmpty() || !allConverters.isEmpty()) { diff --git a/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java b/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java index 42d8b9797b7..bd038304549 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java +++ b/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java @@ -40,6 +40,7 @@ public interface HttpMessageConverters extends Iterable> *
  • {@link StringHttpMessageConverter} with the {@link java.nio.charset.StandardCharsets#ISO_8859_1} charset *
  • {@link ResourceHttpMessageConverter}, with resource streaming support disabled *
  • a Multipart converter, using all detected and custom converters for part conversion + *
  • A Kotlin Serialization converter *
  • A JSON converter *
  • A Smile converter *
  • A CBOR converter @@ -62,6 +63,7 @@ public interface HttpMessageConverters extends Iterable> *
  • {@link StringHttpMessageConverter} with the {@link java.nio.charset.StandardCharsets#ISO_8859_1} charset *
  • {@link ResourceHttpMessageConverter} *
  • {@link ResourceRegionHttpMessageConverter} + *
  • A Kotlin Serialization converter *
  • A JSON converter *
  • A Smile converter *
  • A CBOR converter @@ -94,6 +96,14 @@ public interface HttpMessageConverters extends Iterable> */ T withStringConverter(HttpMessageConverter stringMessageConverter); + /** + * Override the default String {@code HttpMessageConverter} + * with any converter supporting the Kotlin Serialization conversion for JSON. + * @param kotlinSerializationConverter the converter instance to use + * @see org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter + */ + T withKotlinSerializationJsonConverter(HttpMessageConverter kotlinSerializationConverter); + /** * Override the default Jackson 3.x JSON {@code HttpMessageConverter} * with any converter supporting the JSON format. diff --git a/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java b/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java index eb6eb465e8b..1aef37b005a 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java @@ -31,6 +31,7 @@ import org.springframework.http.converter.cbor.JacksonCborHttpMessageConverter; import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter; import org.springframework.http.converter.feed.RssChannelHttpMessageConverter; import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter; +import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter; import org.springframework.http.converter.protobuf.KotlinSerializationProtobufHttpMessageConverter; import org.springframework.http.converter.smile.JacksonSmileHttpMessageConverter; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; @@ -63,42 +64,42 @@ class DefaultHttpMessageConvertersTests { void failsWhenStringConverterDoesNotSupportMediaType() { assertThatIllegalArgumentException() .isThrownBy(() -> HttpMessageConverters.forClient().withStringConverter(new CustomHttpMessageConverter()).build()) - .withMessage("stringMessageConverter should support 'text/plain'"); + .withMessage("stringConverter should support 'text/plain'"); } @Test void failsWhenJsonConverterDoesNotSupportMediaType() { assertThatIllegalArgumentException() .isThrownBy(() -> HttpMessageConverters.forClient().withJsonConverter(new CustomHttpMessageConverter()).build()) - .withMessage("jsonMessageConverter should support 'application/json'"); + .withMessage("jsonConverter should support 'application/json'"); } @Test void failsWhenXmlConverterDoesNotSupportMediaType() { assertThatIllegalArgumentException() .isThrownBy(() -> HttpMessageConverters.forClient().withXmlConverter(new CustomHttpMessageConverter()).build()) - .withMessage("xmlMessageConverter should support 'text/xml'"); + .withMessage("xmlConverter should support 'text/xml'"); } @Test void failsWhenSmileConverterDoesNotSupportMediaType() { assertThatIllegalArgumentException() .isThrownBy(() -> HttpMessageConverters.forClient().withSmileConverter(new CustomHttpMessageConverter()).build()) - .withMessage("smileMessageConverter should support 'application/x-jackson-smile'"); + .withMessage("smileConverter should support 'application/x-jackson-smile'"); } @Test void failsWhenCborConverterDoesNotSupportMediaType() { assertThatIllegalArgumentException() .isThrownBy(() -> HttpMessageConverters.forClient().withCborConverter(new CustomHttpMessageConverter()).build()) - .withMessage("cborMessageConverter should support 'application/cbor'"); + .withMessage("cborConverter should support 'application/cbor'"); } @Test void failsWhenYamlConverterDoesNotSupportMediaType() { assertThatIllegalArgumentException() .isThrownBy(() -> HttpMessageConverters.forClient().withYamlConverter(new CustomHttpMessageConverter()).build()) - .withMessage("yamlMessageConverter should support 'application/yaml'"); + .withMessage("yamlConverter should support 'application/yaml'"); } @@ -110,7 +111,7 @@ class DefaultHttpMessageConvertersTests { var converters = HttpMessageConverters.forClient().registerDefaults().build(); assertThat(converters).hasExactlyElementsOfTypes(ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, ResourceHttpMessageConverter.class, - AllEncompassingFormHttpMessageConverter.class, + AllEncompassingFormHttpMessageConverter.class, KotlinSerializationJsonHttpMessageConverter.class, JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class, JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class, JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class, @@ -124,11 +125,11 @@ class DefaultHttpMessageConvertersTests { assertThat(multipartConverter.getPartConverters()).hasExactlyElementsOfTypes( ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, - ResourceHttpMessageConverter.class, JacksonJsonHttpMessageConverter.class, - JacksonSmileHttpMessageConverter.class, JacksonCborHttpMessageConverter.class, - JacksonYamlHttpMessageConverter.class, JacksonXmlHttpMessageConverter.class, - KotlinSerializationProtobufHttpMessageConverter.class, AtomFeedHttpMessageConverter.class, - RssChannelHttpMessageConverter.class); + ResourceHttpMessageConverter.class, KotlinSerializationJsonHttpMessageConverter.class, + JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class, + JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class, + JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class, + AtomFeedHttpMessageConverter.class, RssChannelHttpMessageConverter.class); } @Test @@ -145,7 +146,7 @@ class DefaultHttpMessageConvertersTests { assertThat(converters).hasExactlyElementsOfTypes( CustomHttpMessageConverter.class, ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, ResourceHttpMessageConverter.class, - AllEncompassingFormHttpMessageConverter.class, + AllEncompassingFormHttpMessageConverter.class, KotlinSerializationJsonHttpMessageConverter.class, JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class, JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class, JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class, @@ -213,7 +214,7 @@ class DefaultHttpMessageConvertersTests { assertThat(converters).hasExactlyElementsOfTypes( ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, ResourceHttpMessageConverter.class, ResourceRegionHttpMessageConverter.class, - AllEncompassingFormHttpMessageConverter.class, + AllEncompassingFormHttpMessageConverter.class, KotlinSerializationJsonHttpMessageConverter.class, JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class, JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class, JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class, @@ -227,11 +228,11 @@ class DefaultHttpMessageConvertersTests { assertThat(multipartConverter.getPartConverters()).hasExactlyElementsOfTypes( ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, - ResourceHttpMessageConverter.class, JacksonJsonHttpMessageConverter.class, - JacksonSmileHttpMessageConverter.class, JacksonCborHttpMessageConverter.class, - JacksonYamlHttpMessageConverter.class, JacksonXmlHttpMessageConverter.class, - KotlinSerializationProtobufHttpMessageConverter.class, AtomFeedHttpMessageConverter.class, - RssChannelHttpMessageConverter.class); + ResourceHttpMessageConverter.class, KotlinSerializationJsonHttpMessageConverter.class, + JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class, + JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class, + JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class, + AtomFeedHttpMessageConverter.class, RssChannelHttpMessageConverter.class); } @Test @@ -249,7 +250,7 @@ class DefaultHttpMessageConvertersTests { CustomHttpMessageConverter.class, ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, ResourceHttpMessageConverter.class, ResourceRegionHttpMessageConverter.class, - AllEncompassingFormHttpMessageConverter.class, + AllEncompassingFormHttpMessageConverter.class, KotlinSerializationJsonHttpMessageConverter.class, JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class, JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class, JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class, diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java index 556c506c0a0..1854381d1a9 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java @@ -605,6 +605,12 @@ class JacksonJsonHttpMessageConverterTests { assertThat(result).contains("\"string\":\"Foo\""); } + @Test + void readEmptyAsNull() throws IOException { + MockHttpInputMessage inputMessage = new MockHttpInputMessage("null".getBytes(StandardCharsets.UTF_8)); + inputMessage.getHeaders().setContentType(new MediaType("application", "json")); + assertThat(this.converter.read(Map.class, inputMessage)).isNull(); + } interface MyInterface { diff --git a/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java index 8ac257ccbac..e34c65e70bf 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java @@ -25,7 +25,6 @@ import java.lang.annotation.Target; import java.net.URI; import java.net.URISyntaxException; import java.util.List; -import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; @@ -339,24 +338,6 @@ class RestClientIntegrationTests { }); } - @ParameterizedRestClientTest - @SuppressWarnings({ "rawtypes", "unchecked" }) - void retrieveJsonNull(ClientHttpRequestFactory requestFactory) throws IOException { - startServer(requestFactory); - - prepareResponse(builder -> builder - .code(200) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .body("null")); - - Map result = this.restClient.get() - .uri("/null") - .retrieve() - .body(Map.class); - - assertThat(result).isNull(); - } - @ParameterizedRestClientTest void retrieveJsonEmpty(ClientHttpRequestFactory requestFactory) throws IOException { startServer(requestFactory); diff --git a/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java b/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java index 0e1ae35ce5b..241b8146497 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java @@ -53,8 +53,6 @@ import org.springframework.http.converter.GenericHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.SmartHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter; -import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter; import org.springframework.util.FileCopyUtils; import org.springframework.web.util.DefaultUriBuilderFactory; @@ -108,18 +106,6 @@ class RestTemplateTests { template.setErrorHandler(errorHandler); } - @Test - void defaultMessageConvertersWithoutKotlinSerialization() { - RestTemplate restTemplate = new RestTemplate(); - List> httpMessageConverters = restTemplate.getMessageConverters(); - assertThat(httpMessageConverters).extracting("class").containsOnlyOnce( - JacksonJsonHttpMessageConverter.class - ); - assertThat(httpMessageConverters).extracting("class").doesNotContain( - KotlinSerializationJsonHttpMessageConverter.class - ); - } - @Test void constructorPreconditions() { assertThatIllegalArgumentException()