From 847629412fe7022dfefb62d837383f2e7dc80521 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Fri, 5 Jun 2020 10:52:09 +0200 Subject: [PATCH] Respect MimeType charset in Jackson codecs Before this commit, Jackson2CodecSupport and subclasses did not check media type encoding in the supportsMimeType method (called from canEncode/canDecode). As a result, the encoder reported that it can write (for instance) "application/json;charset=ISO-8859-1", but in practice wrote the default charset (UTF-8). This commit fixes that bug. Closes: gh-25076 --- .../http/codec/json/Jackson2CodecSupport.java | 26 ++++++++++++++++++- .../codec/cbor/Jackson2CborDecoderTests.java | 16 ++++++++---- .../codec/cbor/Jackson2CborEncoderTests.java | 8 ++++++ .../codec/json/Jackson2JsonDecoderTests.java | 4 +++ .../codec/json/Jackson2JsonEncoderTests.java | 7 +++++ .../codec/json/Jackson2SmileDecoderTests.java | 19 +++++++++----- .../codec/json/Jackson2SmileEncoderTests.java | 7 +++++ 7 files changed, 75 insertions(+), 12 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java index 6162be280c9..63eabcd7501 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java @@ -18,13 +18,18 @@ package org.springframework.http.codec.json; import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; @@ -75,6 +80,9 @@ public abstract class Jackson2CodecSupport { new MimeType("application", "json"), new MimeType("application", "*+json"))); + private static final Map ENCODINGS = jsonEncodings(); + + protected final Log logger = HttpLogging.forLogName(getClass()); @@ -107,7 +115,17 @@ public abstract class Jackson2CodecSupport { protected boolean supportsMimeType(@Nullable MimeType mimeType) { - return (mimeType == null || this.mimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType))); + if (mimeType == null) { + return true; + } + else if (this.mimeTypes.stream().noneMatch(m -> m.isCompatibleWith(mimeType))) { + return false; + } + else if (mimeType.getCharset() != null) { + Charset charset = mimeType.getCharset(); + return ENCODINGS.containsKey(charset.name()); + } + return true; } protected JavaType getJavaType(Type type, @Nullable Class contextClass) { @@ -145,4 +163,10 @@ public abstract class Jackson2CodecSupport { @Nullable protected abstract A getAnnotation(MethodParameter parameter, Class annotType); + private static Map jsonEncodings() { + return EnumSet.allOf(JsonEncoding.class).stream() + .collect(Collectors.toMap(JsonEncoding::getJavaName, Function.identity())); + } + + } diff --git a/spring-web/src/test/java/org/springframework/http/codec/cbor/Jackson2CborDecoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/cbor/Jackson2CborDecoderTests.java index 63eaf2488cf..041ad618b5d 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/cbor/Jackson2CborDecoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/cbor/Jackson2CborDecoderTests.java @@ -16,6 +16,7 @@ package org.springframework.http.codec.cbor; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; @@ -27,13 +28,13 @@ import reactor.core.publisher.Flux; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.testfixture.codec.AbstractDecoderTests; +import org.springframework.http.MediaType; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.util.MimeType; import org.springframework.web.testfixture.xml.Pojo; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.springframework.core.ResolvableType.forClass; import static org.springframework.http.MediaType.APPLICATION_JSON; /** @@ -58,11 +59,16 @@ public class Jackson2CborDecoderTests extends AbstractDecoderTests