From e433d8b66af01f3cd910471a7837e77015a93791 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 16 Aug 2017 15:45:14 +0200 Subject: [PATCH] Polish --- .../codec/json/AbstractJackson2Decoder.java | 10 ++++---- .../codec/json/AbstractJackson2Encoder.java | 4 ++-- .../http/codec/json/Jackson2CodecSupport.java | 24 ++++++++++++------- .../codec/json/Jackson2JsonDecoderTests.java | 23 +++++++++++------- .../codec/json/Jackson2JsonEncoderTests.java | 16 +++++++------ 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java index 1bebaf72227..5178fe94ed5 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java @@ -65,10 +65,10 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple @Override public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) { - JavaType javaType = objectMapper().getTypeFactory().constructType(elementType.getType()); + JavaType javaType = getObjectMapper().getTypeFactory().constructType(elementType.getType()); // Skip String: CharSequenceDecoder + "*/*" comes after return (!CharSequence.class.isAssignableFrom(elementType.resolve(Object.class)) && - objectMapper().canDeserialize(javaType) && supportsMimeType(mimeType)); + getObjectMapper().canDeserialize(javaType) && supportsMimeType(mimeType)); } @Override @@ -89,7 +89,7 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple private Flux tokenize(Publisher input, boolean tokenizeArrayElements) { try { - JsonFactory factory = objectMapper().getFactory(); + JsonFactory factory = getObjectMapper().getFactory(); JsonParser parser = factory.createNonBlockingByteArrayParser(); Jackson2Tokenizer tokenizer = new Jackson2Tokenizer(parser, tokenizeArrayElements); return Flux.from(input).flatMap(tokenizer).doFinally(t -> tokenizer.endOfInput()); @@ -111,8 +111,8 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple Class jsonView = (hints != null ? (Class) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null); ObjectReader reader = (jsonView != null ? - objectMapper().readerWithView(jsonView).forType(javaType) : - objectMapper().readerFor(javaType)); + getObjectMapper().readerWithView(jsonView).forType(javaType) : + getObjectMapper().readerFor(javaType)); return tokens.map(tokenBuffer -> { try { diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java index d8dcb5c3973..26a4ec4f935 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java @@ -81,7 +81,7 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple Class clazz = elementType.resolve(Object.class); return (Object.class == clazz) || !String.class.isAssignableFrom(elementType.resolve(clazz)) && - objectMapper().canSerialize(clazz) && supportsMimeType(mimeType); + getObjectMapper().canSerialize(clazz) && supportsMimeType(mimeType); } @Override @@ -116,7 +116,7 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple JavaType javaType = getJavaType(elementType.getType(), null); Class jsonView = (hints != null ? (Class) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null); ObjectWriter writer = (jsonView != null ? - objectMapper().writerWithView(jsonView) : objectMapper().writer()); + getObjectMapper().writerWithView(jsonView) : getObjectMapper().writer()); if (javaType.isContainerType()) { writer = writer.forType(javaType); 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 a8e93c258c9..035b5a9bf49 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 @@ -56,9 +56,10 @@ public abstract class Jackson2CodecSupport { private static final String JSON_VIEW_HINT_ERROR = "@JsonView only supported for write hints with exactly 1 class argument: "; - protected static final List JSON_MIME_TYPES = Arrays.asList( - new MimeType("application", "json", StandardCharsets.UTF_8), - new MimeType("application", "*+json", StandardCharsets.UTF_8)); + private static final List DEFAULT_MIME_TYPES = Collections.unmodifiableList( + Arrays.asList( + new MimeType("application", "json", StandardCharsets.UTF_8), + new MimeType("application", "*+json", StandardCharsets.UTF_8))); private final ObjectMapper objectMapper; @@ -72,15 +73,23 @@ public abstract class Jackson2CodecSupport { protected Jackson2CodecSupport(ObjectMapper objectMapper, MimeType... mimeTypes) { Assert.notNull(objectMapper, "ObjectMapper must not be null"); this.objectMapper = objectMapper; - this.mimeTypes = Collections.unmodifiableList( - !ObjectUtils.isEmpty(mimeTypes) ? Arrays.asList(mimeTypes) : JSON_MIME_TYPES ); + this.mimeTypes = !ObjectUtils.isEmpty(mimeTypes) ? + Collections.unmodifiableList(Arrays.asList(mimeTypes)) : DEFAULT_MIME_TYPES; } - protected ObjectMapper objectMapper() { + public ObjectMapper getObjectMapper() { return this.objectMapper; } + /** + * Sub-classes should expose this as "decodable" or "encodable" mime types. + */ + protected List getMimeTypes() { + return this.mimeTypes; + } + + protected boolean supportsMimeType(@Nullable MimeType mimeType) { return (mimeType == null || this.mimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType))); } @@ -111,7 +120,4 @@ public abstract class Jackson2CodecSupport { @Nullable protected abstract A getAnnotation(MethodParameter parameter, Class annotType); - protected List getMimeTypes() { - return mimeTypes; - } } diff --git a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java index 32cf14c83d2..0c43228e95c 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java @@ -17,12 +17,12 @@ package org.springframework.http.codec.json; import java.nio.charset.StandardCharsets; +import java.util.Collections; import java.util.List; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; -import org.springframework.util.MimeType; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -33,11 +33,15 @@ import org.springframework.core.codec.DecodingException; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.codec.Pojo; +import org.springframework.util.MimeType; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.springframework.core.ResolvableType.forClass; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.http.MediaType.APPLICATION_XML; @@ -64,19 +68,20 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa assertFalse(decoder.canDecode(forClass(Pojo.class), APPLICATION_XML)); } - @Test(expected = UnsupportedOperationException.class) + @Test // SPR-15866 public void canDecodeWithProvidedMimeType() { MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8); Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(new ObjectMapper(), textJavascript); - assertEquals(1, decoder.getDecodableMimeTypes().size()); - assertTrue(decoder.getDecodableMimeTypes().contains(textJavascript)); - assertTrue(decoder.canDecode(forClass(Pojo.class), textJavascript)); - assertFalse(decoder.canDecode(forClass(Pojo.class), APPLICATION_JSON)); + assertEquals(Collections.singletonList(textJavascript), decoder.getDecodableMimeTypes()); + } + + @Test(expected = UnsupportedOperationException.class) + public void decodableMimeTypesIsImmutable() { + MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8); + Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(new ObjectMapper(), textJavascript); - // Validate immutability of mime types list decoder.getMimeTypes().add(new MimeType("text", "ecmascript")); - assertEquals(1, decoder.getDecodableMimeTypes().size()); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java index cdb0ea5508a..15df132d8fe 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java @@ -18,6 +18,7 @@ package org.springframework.http.codec.json; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Collections; import java.util.Map; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -62,19 +63,20 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa assertTrue(this.encoder.canEncode(ResolvableType.NONE, null)); } - @Test(expected = UnsupportedOperationException.class) + @Test // SPR-15866 public void canEncodeWithCustomMimeType() { - ResolvableType pojoType = ResolvableType.forClass(Pojo.class); MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8); Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(new ObjectMapper(), textJavascript); - assertEquals(1, encoder.getEncodableMimeTypes().size()); - assertTrue(encoder.getEncodableMimeTypes().contains(textJavascript)); - assertTrue(encoder.canEncode(pojoType, textJavascript)); + assertEquals(Collections.singletonList(textJavascript), encoder.getEncodableMimeTypes()); + } + + @Test(expected = UnsupportedOperationException.class) + public void encodableMimeTypesIsImmutable() { + MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8); + Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(new ObjectMapper(), textJavascript); - // Validate immutability of mime types list encoder.getMimeTypes().add(new MimeType("text", "ecmascript")); - assertEquals(1, encoder.getEncodableMimeTypes().size()); } @Test