Skip to content

Commit bb327b9

Browse files
committed
Merge pull request #1499 from rlindooren/SPR-15866-use-provided-mime-types
2 parents 645e349 + e433d8b commit bb327b9

File tree

7 files changed

+68
-16
lines changed

7 files changed

+68
-16
lines changed

spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ protected AbstractJackson2Decoder(ObjectMapper mapper, MimeType... mimeTypes) {
6565

6666
@Override
6767
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
68-
JavaType javaType = objectMapper().getTypeFactory().constructType(elementType.getType());
68+
JavaType javaType = getObjectMapper().getTypeFactory().constructType(elementType.getType());
6969
// Skip String: CharSequenceDecoder + "*/*" comes after
7070
return (!CharSequence.class.isAssignableFrom(elementType.resolve(Object.class)) &&
71-
objectMapper().canDeserialize(javaType) && supportsMimeType(mimeType));
71+
getObjectMapper().canDeserialize(javaType) && supportsMimeType(mimeType));
7272
}
7373

7474
@Override
@@ -89,7 +89,7 @@ public Mono<Object> decodeToMono(Publisher<DataBuffer> input, ResolvableType ele
8989

9090
private Flux<TokenBuffer> tokenize(Publisher<DataBuffer> input, boolean tokenizeArrayElements) {
9191
try {
92-
JsonFactory factory = objectMapper().getFactory();
92+
JsonFactory factory = getObjectMapper().getFactory();
9393
JsonParser parser = factory.createNonBlockingByteArrayParser();
9494
Jackson2Tokenizer tokenizer = new Jackson2Tokenizer(parser, tokenizeArrayElements);
9595
return Flux.from(input).flatMap(tokenizer).doFinally(t -> tokenizer.endOfInput());
@@ -111,8 +111,8 @@ private Flux<Object> decodeInternal(Flux<TokenBuffer> tokens, ResolvableType ele
111111
Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
112112

113113
ObjectReader reader = (jsonView != null ?
114-
objectMapper().readerWithView(jsonView).forType(javaType) :
115-
objectMapper().readerFor(javaType));
114+
getObjectMapper().readerWithView(jsonView).forType(javaType) :
115+
getObjectMapper().readerFor(javaType));
116116

117117
return tokens.map(tokenBuffer -> {
118118
try {

spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType
8181
Class<?> clazz = elementType.resolve(Object.class);
8282
return (Object.class == clazz) ||
8383
!String.class.isAssignableFrom(elementType.resolve(clazz)) &&
84-
objectMapper().canSerialize(clazz) && supportsMimeType(mimeType);
84+
getObjectMapper().canSerialize(clazz) && supportsMimeType(mimeType);
8585
}
8686

8787
@Override
@@ -116,7 +116,7 @@ private DataBuffer encodeValue(Object value, @Nullable MimeType mimeType, DataBu
116116
JavaType javaType = getJavaType(elementType.getType(), null);
117117
Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
118118
ObjectWriter writer = (jsonView != null ?
119-
objectMapper().writerWithView(jsonView) : objectMapper().writer());
119+
getObjectMapper().writerWithView(jsonView) : getObjectMapper().writer());
120120

121121
if (javaType.isContainerType()) {
122122
writer = writer.forType(javaType);

spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ public abstract class Jackson2CodecSupport {
5656
private static final String JSON_VIEW_HINT_ERROR =
5757
"@JsonView only supported for write hints with exactly 1 class argument: ";
5858

59-
protected static final List<MimeType> JSON_MIME_TYPES = Arrays.asList(
60-
new MimeType("application", "json", StandardCharsets.UTF_8),
61-
new MimeType("application", "*+json", StandardCharsets.UTF_8));
59+
private static final List<MimeType> DEFAULT_MIME_TYPES = Collections.unmodifiableList(
60+
Arrays.asList(
61+
new MimeType("application", "json", StandardCharsets.UTF_8),
62+
new MimeType("application", "*+json", StandardCharsets.UTF_8)));
6263

6364

6465
private final ObjectMapper objectMapper;
@@ -72,14 +73,23 @@ public abstract class Jackson2CodecSupport {
7273
protected Jackson2CodecSupport(ObjectMapper objectMapper, MimeType... mimeTypes) {
7374
Assert.notNull(objectMapper, "ObjectMapper must not be null");
7475
this.objectMapper = objectMapper;
75-
this.mimeTypes = !ObjectUtils.isEmpty(mimeTypes) ? Arrays.asList(mimeTypes) : JSON_MIME_TYPES;
76+
this.mimeTypes = !ObjectUtils.isEmpty(mimeTypes) ?
77+
Collections.unmodifiableList(Arrays.asList(mimeTypes)) : DEFAULT_MIME_TYPES;
7678
}
7779

7880

79-
protected ObjectMapper objectMapper() {
81+
public ObjectMapper getObjectMapper() {
8082
return this.objectMapper;
8183
}
8284

85+
/**
86+
* Sub-classes should expose this as "decodable" or "encodable" mime types.
87+
*/
88+
protected List<MimeType> getMimeTypes() {
89+
return this.mimeTypes;
90+
}
91+
92+
8393
protected boolean supportsMimeType(@Nullable MimeType mimeType) {
8494
return (mimeType == null || this.mimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType)));
8595
}

spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ public Jackson2JsonDecoder(ObjectMapper mapper, MimeType... mimeTypes) {
4242

4343
@Override
4444
public List<MimeType> getDecodableMimeTypes() {
45-
return JSON_MIME_TYPES;
45+
return getMimeTypes();
4646
}
4747
}

spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,6 @@ protected ObjectWriter customizeWriter(ObjectWriter writer, @Nullable MimeType m
7373

7474
@Override
7575
public List<MimeType> getEncodableMimeTypes() {
76-
return JSON_MIME_TYPES;
76+
return getMimeTypes();
7777
}
7878
}

spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616

1717
package org.springframework.http.codec.json;
1818

19+
import java.nio.charset.StandardCharsets;
20+
import java.util.Collections;
1921
import java.util.List;
2022
import java.util.Map;
2123

2224
import com.fasterxml.jackson.databind.ObjectMapper;
23-
import org.junit.Ignore;
2425
import org.junit.Test;
2526
import reactor.core.publisher.Flux;
2627
import reactor.core.publisher.Mono;
@@ -32,11 +33,15 @@
3233
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
3334
import org.springframework.core.io.buffer.DataBuffer;
3435
import org.springframework.http.codec.Pojo;
36+
import org.springframework.util.MimeType;
3537

3638
import static java.util.Arrays.asList;
3739
import static java.util.Collections.emptyMap;
3840
import static java.util.Collections.singletonMap;
39-
import static org.junit.Assert.*;
41+
import static org.junit.Assert.assertEquals;
42+
import static org.junit.Assert.assertFalse;
43+
import static org.junit.Assert.assertNull;
44+
import static org.junit.Assert.assertTrue;
4045
import static org.springframework.core.ResolvableType.forClass;
4146
import static org.springframework.http.MediaType.APPLICATION_JSON;
4247
import static org.springframework.http.MediaType.APPLICATION_XML;
@@ -63,6 +68,22 @@ public void canDecode() {
6368
assertFalse(decoder.canDecode(forClass(Pojo.class), APPLICATION_XML));
6469
}
6570

71+
@Test // SPR-15866
72+
public void canDecodeWithProvidedMimeType() {
73+
MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8);
74+
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(new ObjectMapper(), textJavascript);
75+
76+
assertEquals(Collections.singletonList(textJavascript), decoder.getDecodableMimeTypes());
77+
}
78+
79+
@Test(expected = UnsupportedOperationException.class)
80+
public void decodableMimeTypesIsImmutable() {
81+
MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8);
82+
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(new ObjectMapper(), textJavascript);
83+
84+
decoder.getMimeTypes().add(new MimeType("text", "ecmascript"));
85+
}
86+
6687
@Test
6788
public void decodePojo() throws Exception {
6889
Flux<DataBuffer> source = Flux.just(stringBuffer("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}"));

spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,21 @@
1616

1717
package org.springframework.http.codec.json;
1818

19+
import java.nio.charset.StandardCharsets;
1920
import java.util.Arrays;
21+
import java.util.Collections;
2022
import java.util.Map;
2123

2224
import com.fasterxml.jackson.annotation.JsonTypeInfo;
2325
import com.fasterxml.jackson.annotation.JsonTypeName;
2426
import static java.util.Collections.*;
27+
import com.fasterxml.jackson.databind.ObjectMapper;
2528
import org.junit.Test;
29+
import static org.junit.Assert.assertEquals;
2630
import static org.springframework.http.MediaType.*;
2731
import static org.springframework.http.codec.json.Jackson2JsonEncoder.*;
2832
import static org.springframework.http.codec.json.JacksonViewBean.*;
33+
import org.springframework.util.MimeType;
2934
import reactor.core.publisher.Flux;
3035
import reactor.core.publisher.Mono;
3136
import reactor.test.StepVerifier;
@@ -58,6 +63,22 @@ public void canEncode() {
5863
assertTrue(this.encoder.canEncode(ResolvableType.NONE, null));
5964
}
6065

66+
@Test // SPR-15866
67+
public void canEncodeWithCustomMimeType() {
68+
MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8);
69+
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(new ObjectMapper(), textJavascript);
70+
71+
assertEquals(Collections.singletonList(textJavascript), encoder.getEncodableMimeTypes());
72+
}
73+
74+
@Test(expected = UnsupportedOperationException.class)
75+
public void encodableMimeTypesIsImmutable() {
76+
MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8);
77+
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(new ObjectMapper(), textJavascript);
78+
79+
encoder.getMimeTypes().add(new MimeType("text", "ecmascript"));
80+
}
81+
6182
@Test
6283
public void canNotEncode() {
6384
assertFalse(this.encoder.canEncode(ResolvableType.forClass(String.class), null));

0 commit comments

Comments
 (0)