From 6959e66b25785b4ad056791517411b5fb762ab9f Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 21 Feb 2018 10:12:33 -0500 Subject: [PATCH] JsonEOFException is wrapped as DecodingError Jackson2Tokenizer now also wraps JsonProcessingException's on endOfInput(), as it also does in tokenize(DataBuffer). This ensures treating those errors as 400 vs 500. Issue: SPR-16521 --- .../http/codec/json/Jackson2Tokenizer.java | 6 ++++-- .../http/codec/json/Jackson2TokenizerTests.java | 13 +++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2Tokenizer.java b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2Tokenizer.java index 15aba7c5c6..acb64b049c 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2Tokenizer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/Jackson2Tokenizer.java @@ -27,7 +27,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.async.ByteArrayFeeder; import com.fasterxml.jackson.databind.util.TokenBuffer; -import org.jetbrains.annotations.NotNull; import reactor.core.publisher.Flux; import org.springframework.core.codec.DecodingException; @@ -114,12 +113,15 @@ class Jackson2Tokenizer { try { return parseTokenBufferFlux(); } + catch (JsonProcessingException ex) { + return Flux.error(new DecodingException( + "JSON decoding error: " + ex.getOriginalMessage(), ex)); + } catch (IOException ex) { return Flux.error(ex); } } - @NotNull private Flux parseTokenBufferFlux() throws IOException { List result = new ArrayList<>(); diff --git a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2TokenizerTests.java b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2TokenizerTests.java index 2d76831162..952b17d796 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2TokenizerTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2TokenizerTests.java @@ -32,11 +32,12 @@ import org.skyscreamer.jsonassert.JSONAssert; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; +import org.springframework.core.codec.DecodingException; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; +import static java.util.Arrays.*; +import static java.util.Collections.*; /** * @author Arjen Poutsma @@ -174,6 +175,14 @@ public class Jackson2TokenizerTests extends AbstractDataBufferAllocatingTestCase asList("1", "2", "3"), true); } + @Test(expected = DecodingException.class) // SPR-16521 + public void jsonEOFExceptionIsWrappedAsDecodingError() { + Flux source = Flux.just(stringBuffer("{\"status\": \"noClosingQuote}")); + Flux tokens = Jackson2Tokenizer.tokenize(source, this.jsonFactory, false); + tokens.blockLast(); + } + + private void testTokenize(List source, List expected, boolean tokenizeArrayElements) { Flux sourceFlux = Flux.fromIterable(source) .map(this::stringBuffer);