From 3efb76c85285bd9899552dd2cb57ec3ae1920174 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 14 Apr 2017 17:18:44 -0400 Subject: [PATCH] Jackson encoder skips String.class Jackson2Encoder explicitly disables String from the supported types consistent with the same change on the decoder side: https://github.com/spring-projects/spring-framework/commit/0662dbf0447d8e788575fcf73fafe248b74cbe8d Issue: SPR-15443 --- .../server/samples/JsonContentTests.java | 24 +++++++++++++++++-- .../server/samples/ResponseEntityTests.java | 3 +-- .../http/codec/json/Jackson2JsonDecoder.java | 2 +- .../http/codec/json/Jackson2JsonEncoder.java | 4 +++- .../codec/json/Jackson2JsonEncoderTests.java | 8 ++++++- .../ResponseEntityResultHandlerTests.java | 2 +- .../view/HttpMessageWriterViewTests.java | 16 ++++++------- 7 files changed, 43 insertions(+), 16 deletions(-) diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java index f1fc414eaf..184525ac69 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java @@ -15,17 +15,22 @@ */ package org.springframework.test.web.reactive.server.samples; +import java.net.URI; + import org.junit.Test; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; /** - * Sample tests asserting JSON response content. + * Samples of tests with serialized JSON content. * * @author Rossen Stoyanchev */ @@ -55,6 +60,16 @@ public class JsonContentTests { .jsonPath("$[2].name").isEqualTo("John"); } + @Test + public void postJsonContent() throws Exception { + this.client.post().uri("/persons") + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body("{\"name\":\"John\"}") + .exchange() + .expectStatus().isCreated() + .expectBody().isEmpty(); + } + @RestController @SuppressWarnings("unused") @@ -64,6 +79,11 @@ public class JsonContentTests { Flux getPersons() { return Flux.just(new Person("Jane"), new Person("Jason"), new Person("John")); } + + @PostMapping + ResponseEntity savePerson(@RequestBody Person person) { + return ResponseEntity.created(URI.create("/persons/" + person.getName())).build(); + } } } diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java index 19f7dc2472..a8d4680927 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/ResponseEntityTests.java @@ -24,7 +24,6 @@ import java.util.Map; import org.junit.Test; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import org.springframework.http.MediaType; @@ -124,7 +123,7 @@ public class ResponseEntityTests { @Test public void postEntity() throws Exception { this.client.post().uri("/persons") - .body(Mono.just(new Person("John")), Person.class) + .body(new Person("John")) .exchange() .expectStatus().isCreated() .expectHeader().valueEquals("location", "/persons/John") diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java index bbb5f4724b..3333558aaa 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonDecoder.java @@ -69,7 +69,7 @@ public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMes @Override public boolean canDecode(ResolvableType elementType, MimeType mimeType) { JavaType javaType = this.objectMapper.getTypeFactory().constructType(elementType.getType()); - // Skip String (CharSequenceDecoder + "*/*" comes after) + // Skip String: CharSequenceDecoder + "*/*" comes after return (!CharSequence.class.isAssignableFrom(elementType.resolve(Object.class)) && this.objectMapper.canDeserialize(javaType) && supportsMimeType(mimeType)); } diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java index 467d773ca0..54843adb0c 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2JsonEncoder.java @@ -105,7 +105,9 @@ public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMes @Override public boolean canEncode(ResolvableType elementType, MimeType mimeType) { Class clazz = elementType.getRawClass(); - return (this.objectMapper.canSerialize(clazz) && supportsMimeType(mimeType)); + // Skip String: StringDecoder + "*/*" comes after + return (!String.class.isAssignableFrom(elementType.resolve(Object.class)) && + this.objectMapper.canSerialize(clazz) && supportsMimeType(mimeType)); } @Override 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 6c808311c2..56d7c83cab 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 @@ -52,7 +52,13 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa ResolvableType pojoType = ResolvableType.forClass(Pojo.class); assertTrue(this.encoder.canEncode(pojoType, APPLICATION_JSON)); assertTrue(this.encoder.canEncode(pojoType, null)); - assertFalse(this.encoder.canEncode(pojoType, APPLICATION_XML)); + } + + @Test + public void canNotEncode() { + assertFalse(this.encoder.canEncode(ResolvableType.forClass(String.class), null)); + assertFalse(this.encoder.canEncode(ResolvableType.forClass(Pojo.class), APPLICATION_XML)); + ResolvableType sseType = ResolvableType.forClass(ServerSentEvent.class); assertFalse(this.encoder.canEncode(sseType, APPLICATION_JSON)); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java index b133379379..f27fb75b34 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java @@ -291,7 +291,7 @@ public class ResponseEntityResultHandlerTests { this.resultHandler.handleResult(exchange, result).block(Duration.ofSeconds(5)); assertEquals(HttpStatus.OK, exchange.getResponse().getStatusCode()); - assertResponseBody(exchange, "\"body\""); + assertResponseBody(exchange, "body"); } @Test // SPR-14877 diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java index 2a25353e0f..356baf4f32 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java @@ -67,11 +67,11 @@ public class HttpMessageWriterViewTests { @Test public void singleMatch() throws Exception { this.view.setModelKeys(Collections.singleton("foo2")); - this.model.addAttribute("foo1", "bar1"); - this.model.addAttribute("foo2", "bar2"); - this.model.addAttribute("foo3", "bar3"); + this.model.addAttribute("foo1", Collections.singleton("bar1")); + this.model.addAttribute("foo2", Collections.singleton("bar2")); + this.model.addAttribute("foo3", Collections.singleton("bar3")); - assertEquals("\"bar2\"", doRender()); + assertEquals("[\"bar2\"]", doRender()); } @Test @@ -94,11 +94,11 @@ public class HttpMessageWriterViewTests { @Test public void multipleMatches() throws Exception { this.view.setModelKeys(new HashSet<>(Arrays.asList("foo1", "foo2"))); - this.model.addAttribute("foo1", "bar1"); - this.model.addAttribute("foo2", "bar2"); - this.model.addAttribute("foo3", "bar3"); + this.model.addAttribute("foo1", Collections.singleton("bar1")); + this.model.addAttribute("foo2", Collections.singleton("bar2")); + this.model.addAttribute("foo3", Collections.singleton("bar3")); - assertEquals("{\"foo1\":\"bar1\",\"foo2\":\"bar2\"}", doRender()); + assertEquals("{\"foo1\":[\"bar1\"],\"foo2\":[\"bar2\"]}", doRender()); } @Test