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 e6fd0221ab..f794f439dc 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 @@ -111,20 +111,23 @@ public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMes this.objectMapper.readerFor(javaType)); return objectDecoder.decode(inputStream, elementType, mimeType, hints) - .map(dataBuffer -> { + .flatMap(dataBuffer -> { + if (dataBuffer.readableByteCount() == 0) { + return Mono.empty(); + } try { Object value = reader.readValue(dataBuffer.asInputStream()); DataBufferUtils.release(dataBuffer); - return value; + return Mono.just(value); } catch (InvalidDefinitionException ex) { - throw new CodecException("Type definition error: " + ex.getType(), ex); + return Mono.error(new CodecException("Type definition error: " + ex.getType(), ex)); } catch (JsonProcessingException ex) { - throw new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex); + return Mono.error(new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex)); } catch (IOException ex) { - throw new DecodingException("I/O error while parsing input stream", ex); + return Mono.error(new DecodingException("I/O error while parsing input stream", ex)); } }); } 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 d96fcfb66a..019776921c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,9 +35,7 @@ import org.springframework.http.codec.Pojo; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import static org.springframework.core.ResolvableType.forClass; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.http.MediaType.APPLICATION_XML; @@ -116,6 +114,19 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa .verifyComplete(); } + @Test + public void decodeEmptyArrayToFlux() throws Exception { + Flux source = Flux.just(stringBuffer("[]")); + + ResolvableType elementType = forClass(Pojo.class); + Flux flux = new Jackson2JsonDecoder().decode(source, elementType, null, + emptyMap()); + + StepVerifier.create(flux) + .expectNextCount(0) + .verifyComplete(); + } + @Test public void fieldLevelJsonView() throws Exception { Flux source = Flux.just( @@ -164,6 +175,18 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa .verifyComplete(); } + @Test + public void decodeEmptyArrayToMono() throws Exception { + Flux source = Flux.just(stringBuffer("[]")); + ResolvableType elementType = forClass(Pojo.class); + Mono mono = new Jackson2JsonDecoder().decodeToMono(source, elementType, + null, emptyMap()); + + StepVerifier.create(mono) + .expectNextCount(0) + .verifyComplete(); + } + @Test public void invalidData() throws Exception { Flux source = Flux.just(stringBuffer( "{\"foofoo\": \"foofoo\", \"barbar\": \"barbar\"}"));