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 6393f39cb4c..5a72994c3ed 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 @@ -20,6 +20,7 @@ import java.io.IOException; import java.math.BigDecimal; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -47,12 +48,8 @@ import org.springframework.http.codec.json.JacksonViewBean.MyJacksonView3; import org.springframework.util.MimeType; import org.springframework.web.testfixture.xml.Pojo; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.springframework.core.ResolvableType.forClass; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.http.MediaType.APPLICATION_STREAM_JSON; import static org.springframework.http.MediaType.APPLICATION_XML; @@ -79,12 +76,12 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests step - .expectNext(asList(new Pojo("f1", "b1"), new Pojo("f2", "b2"))) + .expectNext(Arrays.asList(new Pojo("f1", "b1"), new Pojo("f2", "b2"))) .expectComplete() .verify(), null, null); } @@ -143,22 +140,23 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests input = Flux.from(stringBuffer("[]")); - testDecode(input, Pojo.class, step -> step.verifyComplete()); + testDecode(input, Pojo.class, StepVerifier.LastStep::verifyComplete); } @Test public void fieldLevelJsonView() { - Flux input = Flux.from( - stringBuffer("{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}")); - ResolvableType elementType = forClass(JacksonViewBean.class); - Map hints = singletonMap(JSON_VIEW_HINT, MyJacksonView1.class); + Flux input = Flux.from(stringBuffer( + "{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}")); + + ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class); + Map hints = Collections.singletonMap(JSON_VIEW_HINT, MyJacksonView1.class); testDecode(input, elementType, step -> step - .consumeNextWith(o -> { - JacksonViewBean b = (JacksonViewBean) o; - assertThat(b.getWithView1()).isEqualTo("with"); - assertThat(b.getWithView2()).isNull(); - assertThat(b.getWithoutView()).isNull(); + .consumeNextWith(value -> { + JacksonViewBean bean = (JacksonViewBean) value; + assertThat(bean.getWithView1()).isEqualTo("with"); + assertThat(bean.getWithView2()).isNull(); + assertThat(bean.getWithoutView()).isNull(); }), null, hints); } @@ -166,25 +164,24 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests input = Flux.from(stringBuffer( "{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}")); - ResolvableType elementType = forClass(JacksonViewBean.class); - Map hints = singletonMap(JSON_VIEW_HINT, MyJacksonView3.class); + + ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class); + Map hints = Collections.singletonMap(JSON_VIEW_HINT, MyJacksonView3.class); testDecode(input, elementType, step -> step - .consumeNextWith(o -> { - JacksonViewBean b = (JacksonViewBean) o; - assertThat(b.getWithoutView()).isEqualTo("without"); - assertThat(b.getWithView1()).isNull(); - assertThat(b.getWithView2()).isNull(); + .consumeNextWith(value -> { + JacksonViewBean bean = (JacksonViewBean) value; + assertThat(bean.getWithoutView()).isEqualTo("without"); + assertThat(bean.getWithView1()).isNull(); + assertThat(bean.getWithView2()).isNull(); }) .verifyComplete(), null, hints); } @Test public void invalidData() { - Flux input = - Flux.from(stringBuffer("{\"foofoo\": \"foofoo\", \"barbar\": \"barbar\"")); - testDecode(input, Pojo.class, step -> step - .verifyError(DecodingException.class)); + Flux input = Flux.from(stringBuffer("{\"foofoo\": \"foofoo\", \"barbar\": \"barbar\"")); + testDecode(input, Pojo.class, step -> step.verifyError(DecodingException.class)); } @Test // gh-22042 @@ -197,10 +194,9 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests input = - Flux.from(stringBuffer("{\"property1\":\"foo\",\"property2\":\"bar\"}")); - ResolvableType elementType = forClass(BeanWithNoDefaultConstructor.class); - Flux flux = new Jackson2JsonDecoder().decode(input, elementType, null, emptyMap()); + Flux input = Flux.from(stringBuffer("{\"property1\":\"foo\",\"property2\":\"bar\"}")); + ResolvableType elementType = ResolvableType.forClass(BeanWithNoDefaultConstructor.class); + Flux flux = new Jackson2JsonDecoder().decode(input, elementType, null, Collections.emptyMap()); StepVerifier.create(flux).verifyError(CodecException.class); } @@ -228,9 +224,10 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests input = stringBuffer("{\"foo\":\"bar\"}", StandardCharsets.UTF_16); + ResolvableType type = ResolvableType.forType(new ParameterizedTypeReference>() {}); - testDecode(input, ResolvableType.forType(new ParameterizedTypeReference>() {}), - step -> step.assertNext(o -> assertThat((Map) o).containsEntry("foo", "bar")) + testDecode(input, type, step -> step + .assertNext(value -> assertThat((Map) value).containsEntry("foo", "bar")) .verifyComplete(), MediaType.parseMediaType("application/json; charset=utf-16"), null); @@ -239,12 +236,11 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests input = Flux.concat( - stringBuffer("{\"føø\":\"bår\"}", StandardCharsets.ISO_8859_1) - ); + Flux input = Flux.concat(stringBuffer("{\"føø\":\"bår\"}", StandardCharsets.ISO_8859_1)); + ResolvableType type = ResolvableType.forType(new ParameterizedTypeReference>() {}); - testDecode(input, ResolvableType.forType(new ParameterizedTypeReference>() {}), - step -> step.assertNext(o -> assertThat((Map) o).containsEntry("føø", "bår")) + testDecode(input, type, step -> step + .assertNext(o -> assertThat((Map) o).containsEntry("føø", "bår")) .verifyComplete(), MediaType.parseMediaType("application/json; charset=iso-8859-1"), null); @@ -254,9 +250,10 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests input = stringBuffer("{\"foo\":\"bar\"}", StandardCharsets.UTF_16); + ResolvableType type = ResolvableType.forType(new ParameterizedTypeReference>() {}); - testDecodeToMono(input, ResolvableType.forType(new ParameterizedTypeReference>() {}), - step -> step.assertNext(o -> assertThat((Map) o).containsEntry("foo", "bar")) + testDecodeToMono(input, type, step -> step + .assertNext(value -> assertThat((Map) value).containsEntry("foo", "bar")) .verifyComplete(), MediaType.parseMediaType("application/json; charset=utf-16"), null); @@ -265,12 +262,11 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests input = Flux.concat( - stringBuffer("{\"foo\":\"bar\"}", StandardCharsets.US_ASCII) - ); + Flux input = Flux.concat(stringBuffer("{\"foo\":\"bar\"}", StandardCharsets.US_ASCII)); + ResolvableType type = ResolvableType.forType(new ParameterizedTypeReference>() {}); - testDecode(input, ResolvableType.forType(new ParameterizedTypeReference>() {}), - step -> step.assertNext(o -> assertThat((Map) o).containsEntry("foo", "bar")) + testDecode(input, type, step -> step + .assertNext(value -> assertThat((Map) value).containsEntry("foo", "bar")) .verifyComplete(), MediaType.parseMediaType("application/json; charset=us-ascii"), null); @@ -291,7 +287,6 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTests { + private static class Deserializer extends StdDeserializer { private static final long serialVersionUID = 1L; 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 501e9b4bbff..e75c4451c5d 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 @@ -72,46 +72,43 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTests { singletonList("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}"), false); testTokenize( - asList("{\"foo\": \"foofoo\"", - ", \"bar\": \"barbar\"}"), + asList( + "{\"foo\": \"foofoo\"", + ", \"bar\": \"barbar\"}" + ), singletonList("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}"), false); testTokenize( - singletonList("[" + - "{\"foo\": \"foofoo\", \"bar\": \"barbar\"}," + - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), - singletonList("[" + - "{\"foo\": \"foofoo\", \"bar\": \"barbar\"}," + - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), false); + singletonList("[{\"foo\": \"foofoo\", \"bar\": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), + singletonList("[{\"foo\": \"foofoo\", \"bar\": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), + false); testTokenize( singletonList("[{\"foo\": \"bar\"},{\"foo\": \"baz\"}]"), singletonList("[{\"foo\": \"bar\"},{\"foo\": \"baz\"}]"), false); testTokenize( - asList("[" + - "{\"foo\": \"foofoo\", \"bar\"", ": \"barbar\"}," + - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), - singletonList("[" + - "{\"foo\": \"foofoo\", \"bar\": \"barbar\"}," + - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), false); + asList( + "[{\"foo\": \"foofoo\", \"bar\"", + ": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]" + ), + singletonList("[{\"foo\": \"foofoo\", \"bar\": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), + false); testTokenize( - asList("[", + asList( + "[", "{\"id\":1,\"name\":\"Robert\"}", ",", "{\"id\":2,\"name\":\"Raide\"}", ",", - "{\"id\":3,\"name\":\"Ford\"}", "]"), - singletonList("[" + - "{\"id\":1,\"name\":\"Robert\"}," + - "{\"id\":2,\"name\":\"Raide\"}," + - "{\"id\":3,\"name\":\"Ford\"}]"), false); + "{\"id\":3,\"name\":\"Ford\"}", "]" + ), + singletonList("[{\"id\":1,\"name\":\"Robert\"},{\"id\":2,\"name\":\"Raide\"},{\"id\":3,\"name\":\"Ford\"}]"), + false); // SPR-16166: top-level JSON values - testTokenize(asList("\"foo", "bar\""),singletonList("\"foobar\""), false); - - testTokenize(asList("12", "34"),singletonList("1234"), false); - - testTokenize(asList("12.", "34"),singletonList("12.34"), false); + testTokenize(asList("\"foo", "bar\""), singletonList("\"foobar\""), false); + testTokenize(asList("12", "34"), singletonList("1234"), false); + testTokenize(asList("12.", "34"), singletonList("12.34"), false); // note that we do not test for null, true, or false, which are also valid top-level values, // but are unsupported by JSONassert @@ -124,20 +121,27 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTests { singletonList("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}"), true); testTokenize( - asList("{\"foo\": \"foofoo\"", ", \"bar\": \"barbar\"}"), + asList( + "{\"foo\": \"foofoo\"", + ", \"bar\": \"barbar\"}" + ), singletonList("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}"), true); testTokenize( - singletonList("[" + - "{\"foo\": \"foofoo\", \"bar\": \"barbar\"}," + - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), + singletonList("[{\"foo\": \"foofoo\", \"bar\": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), asList( "{\"foo\": \"foofoo\", \"bar\": \"barbar\"}", - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}"), true); + "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}" + ), + true); testTokenize( singletonList("[{\"foo\": \"bar\"},{\"foo\": \"baz\"}]"), - asList("{\"foo\": \"bar\"}", "{\"foo\": \"baz\"}"), true); + asList( + "{\"foo\": \"bar\"}", + "{\"foo\": \"baz\"}" + ), + true); // SPR-15803: nested array testTokenize( @@ -149,7 +153,9 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTests { asList( "{\"id\":\"0\",\"start\":[-999999999,1,1],\"end\":[999999999,12,31]}", "{\"id\":\"1\",\"start\":[-999999999,1,1],\"end\":[999999999,12,31]}", - "{\"id\":\"2\",\"start\":[-999999999,1,1],\"end\":[999999999,12,31]}"), true); + "{\"id\":\"2\",\"start\":[-999999999,1,1],\"end\":[999999999,12,31]}" + ), + true); // SPR-15803: nested array, no top-level array testTokenize( @@ -157,31 +163,35 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTests { singletonList("{\"speakerIds\":[\"tastapod\"],\"language\":\"ENGLISH\"}"), true); testTokenize( - asList("[" + - "{\"foo\": \"foofoo\", \"bar\"", ": \"barbar\"}," + - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]"), + asList( + "[{\"foo\": \"foofoo\", \"bar\"", + ": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]" + ), asList( "{\"foo\": \"foofoo\", \"bar\": \"barbar\"}", "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}"), true); testTokenize( - asList("[", + asList( + "[", "{\"id\":1,\"name\":\"Robert\"}", ",", "{\"id\":2,\"name\":\"Raide\"}", ",", "{\"id\":3,\"name\":\"Ford\"}", - "]"), - asList("{\"id\":1,\"name\":\"Robert\"}", + "]" + ), + asList( + "{\"id\":1,\"name\":\"Robert\"}", "{\"id\":2,\"name\":\"Raide\"}", - "{\"id\":3,\"name\":\"Ford\"}"), true); + "{\"id\":3,\"name\":\"Ford\"}" + ), + true); // SPR-16166: top-level JSON values - testTokenize(asList("\"foo", "bar\""),singletonList("\"foobar\""), true); - - testTokenize(asList("12", "34"),singletonList("1234"), true); - - testTokenize(asList("12.", "34"),singletonList("12.34"), true); + testTokenize(asList("\"foo", "bar\""), singletonList("\"foobar\""), true); + testTokenize(asList("12", "34"), singletonList("1234"), true); + testTokenize(asList("12.", "34"), singletonList("12.34"), true); // SPR-16407 testTokenize(asList("[1", ",2,", "3]"), asList("1", "2", "3"), true); @@ -202,12 +212,13 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTests { @Test public void testLimit() { - - List source = asList("[", + List source = asList( + "[", "{", "\"id\":1,\"name\":\"Dan\"", "},", "{", "\"id\":2,\"name\":\"Ron\"", "},", "{", "\"id\":3,\"name\":\"Bartholomew\"", "}", - "]"); + "]" + ); String expected = String.join("", source); int maxInMemorySize = expected.length(); @@ -223,11 +234,13 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTests { @Test public void testLimitTokenized() { - List source = asList("[", + List source = asList( + "[", "{", "\"id\":1, \"name\":\"Dan\"", "},", "{", "\"id\":2, \"name\":\"Ron\"", "},", "{", "\"id\":3, \"name\":\"Bartholomew\"", "}", - "]"); + "]" + ); String expected = "{\"id\":3,\"name\":\"Bartholomew\"}"; int maxInMemorySize = expected.length(); @@ -271,7 +284,8 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTests { @ValueSource(booleans = {false, true}) public void useBigDecimalForFloats(boolean useBigDecimalForFloats) { Flux source = Flux.just(stringBuffer("1E+2")); - Flux tokens = Jackson2Tokenizer.tokenize(source, this.jsonFactory, this.objectMapper, false, useBigDecimalForFloats, -1); + Flux tokens = Jackson2Tokenizer.tokenize( + source, this.jsonFactory, this.objectMapper, false, useBigDecimalForFloats, -1); StepVerifier.create(tokens) .assertNext(tokenBuffer -> {