Support for ASCII in Jackson codec & converter
This commit introduces support for writing JSON with an US-ASCII character encoding in the Jackson encoder and message converter, treating it like UTF-8. See gh-25322
This commit is contained in:
@@ -87,6 +87,8 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests<Jackson2JsonD
|
||||
assertThat(decoder.canDecode(forClass(Pojo.class), APPLICATION_XML)).isFalse();
|
||||
assertThat(this.decoder.canDecode(ResolvableType.forClass(Pojo.class),
|
||||
new MediaType("application", "json", StandardCharsets.UTF_8))).isTrue();
|
||||
assertThat(this.decoder.canDecode(ResolvableType.forClass(Pojo.class),
|
||||
new MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue();
|
||||
assertThat(this.decoder.canDecode(ResolvableType.forClass(Pojo.class),
|
||||
new MediaType("application", "json", StandardCharsets.ISO_8859_1))).isTrue();
|
||||
}
|
||||
@@ -227,8 +229,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests<Jackson2JsonD
|
||||
public void decodeNonUtf8Encoding() {
|
||||
Mono<DataBuffer> input = stringBuffer("{\"foo\":\"bar\"}", StandardCharsets.UTF_16);
|
||||
|
||||
testDecode(input, ResolvableType.forType(new ParameterizedTypeReference<Map<String, String>>() {
|
||||
}),
|
||||
testDecode(input, ResolvableType.forType(new ParameterizedTypeReference<Map<String, String>>() {}),
|
||||
step -> step.assertNext(o -> assertThat((Map<String, String>) o).containsEntry("foo", "bar"))
|
||||
.verifyComplete(),
|
||||
MediaType.parseMediaType("application/json; charset=utf-16"),
|
||||
@@ -242,8 +243,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests<Jackson2JsonD
|
||||
stringBuffer("{\"føø\":\"bår\"}", StandardCharsets.ISO_8859_1)
|
||||
);
|
||||
|
||||
testDecode(input, ResolvableType.forType(new ParameterizedTypeReference<Map<String, String>>() {
|
||||
}),
|
||||
testDecode(input, ResolvableType.forType(new ParameterizedTypeReference<Map<String, String>>() {}),
|
||||
step -> step.assertNext(o -> assertThat((Map<String, String>) o).containsEntry("føø", "bår"))
|
||||
.verifyComplete(),
|
||||
MediaType.parseMediaType("application/json; charset=iso-8859-1"),
|
||||
@@ -255,14 +255,28 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests<Jackson2JsonD
|
||||
public void decodeMonoNonUtf8Encoding() {
|
||||
Mono<DataBuffer> input = stringBuffer("{\"foo\":\"bar\"}", StandardCharsets.UTF_16);
|
||||
|
||||
testDecodeToMono(input, ResolvableType.forType(new ParameterizedTypeReference<Map<String, String>>() {
|
||||
}),
|
||||
testDecodeToMono(input, ResolvableType.forType(new ParameterizedTypeReference<Map<String, String>>() {}),
|
||||
step -> step.assertNext(o -> assertThat((Map<String, String>) o).containsEntry("foo", "bar"))
|
||||
.verifyComplete(),
|
||||
MediaType.parseMediaType("application/json; charset=utf-16"),
|
||||
null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void decodeAscii() {
|
||||
Flux<DataBuffer> input = Flux.concat(
|
||||
stringBuffer("{\"foo\":\"bar\"}", StandardCharsets.US_ASCII)
|
||||
);
|
||||
|
||||
testDecode(input, ResolvableType.forType(new ParameterizedTypeReference<Map<String, String>>() {}),
|
||||
step -> step.assertNext(o -> assertThat((Map<String, String>) o).containsEntry("foo", "bar"))
|
||||
.verifyComplete(),
|
||||
MediaType.parseMediaType("application/json; charset=us-ascii"),
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
private Mono<DataBuffer> stringBuffer(String value) {
|
||||
return stringBuffer(value, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ public class Jackson2JsonEncoderTests extends AbstractEncoderTests<Jackson2JsonE
|
||||
|
||||
assertThat(this.encoder.canEncode(ResolvableType.forClass(Pojo.class),
|
||||
new MediaType("application", "json", StandardCharsets.UTF_8))).isTrue();
|
||||
assertThat(this.encoder.canEncode(ResolvableType.forClass(Pojo.class),
|
||||
new MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue();
|
||||
assertThat(this.encoder.canEncode(ResolvableType.forClass(Pojo.class),
|
||||
new MediaType("application", "json", StandardCharsets.ISO_8859_1))).isFalse();
|
||||
|
||||
@@ -225,6 +227,17 @@ public class Jackson2JsonEncoderTests extends AbstractEncoderTests<Jackson2JsonE
|
||||
.verify(Duration.ofSeconds(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeAscii() {
|
||||
Mono<Object> input = Mono.just(new Pojo("foo", "bar"));
|
||||
|
||||
testEncode(input, ResolvableType.forClass(Pojo.class), step -> step
|
||||
.consumeNextWith(expectString("{\"foo\":\"foo\",\"bar\":\"bar\"}"))
|
||||
.verifyComplete(),
|
||||
new MimeType("application", "json", StandardCharsets.US_ASCII), null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
private static class ParentClass {
|
||||
|
||||
@@ -67,6 +67,7 @@ public class MappingJackson2HttpMessageConverterTests {
|
||||
assertThat(converter.canRead(MyBean.class, new MediaType("application", "json"))).isTrue();
|
||||
assertThat(converter.canRead(Map.class, new MediaType("application", "json"))).isTrue();
|
||||
assertThat(converter.canRead(MyBean.class, new MediaType("application", "json", StandardCharsets.UTF_8))).isTrue();
|
||||
assertThat(converter.canRead(MyBean.class, new MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue();
|
||||
assertThat(converter.canRead(MyBean.class, new MediaType("application", "json", StandardCharsets.ISO_8859_1))).isTrue();
|
||||
}
|
||||
|
||||
@@ -75,6 +76,7 @@ public class MappingJackson2HttpMessageConverterTests {
|
||||
assertThat(converter.canWrite(MyBean.class, new MediaType("application", "json"))).isTrue();
|
||||
assertThat(converter.canWrite(Map.class, new MediaType("application", "json"))).isTrue();
|
||||
assertThat(converter.canWrite(MyBean.class, new MediaType("application", "json", StandardCharsets.UTF_8))).isTrue();
|
||||
assertThat(converter.canWrite(MyBean.class, new MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue();
|
||||
assertThat(converter.canWrite(MyBean.class, new MediaType("application", "json", StandardCharsets.ISO_8859_1))).isFalse();
|
||||
}
|
||||
|
||||
@@ -460,6 +462,33 @@ public class MappingJackson2HttpMessageConverterTests {
|
||||
assertThat(result).containsExactly(entry("føø", "bår"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readAscii() throws Exception {
|
||||
String body = "{\"foo\":\"bar\"}";
|
||||
Charset charset = StandardCharsets.US_ASCII;
|
||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(charset));
|
||||
inputMessage.getHeaders().setContentType(new MediaType("application", "json", charset));
|
||||
HashMap<String, Object> result = (HashMap<String, Object>) this.converter.read(HashMap.class, inputMessage);
|
||||
|
||||
assertThat(result).containsExactly(entry("foo", "bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void writeAscii() throws Exception {
|
||||
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
|
||||
Map<String,Object> body = new HashMap<>();
|
||||
body.put("foo", "bar");
|
||||
Charset charset = StandardCharsets.US_ASCII;
|
||||
MediaType contentType = new MediaType("application", "json", charset);
|
||||
converter.write(body, contentType, outputMessage);
|
||||
|
||||
String result = outputMessage.getBodyAsString(charset);
|
||||
assertThat(result).isEqualTo("{\"foo\":\"bar\"}");
|
||||
assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(contentType);
|
||||
}
|
||||
|
||||
|
||||
interface MyInterface {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user