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 96836c5332b..d26fefbec01 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 @@ -16,13 +16,15 @@ package org.springframework.http.codec.json; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map; -import com.fasterxml.jackson.annotation.JsonView; +import static java.util.Arrays.asList; +import static java.util.Collections.*; import org.junit.Test; +import static org.springframework.http.MediaType.*; +import static org.springframework.http.codec.json.Jackson2JsonDecoder.*; +import static org.springframework.http.codec.json.JacksonViewBean.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -31,7 +33,6 @@ import org.springframework.core.ResolvableType; import org.springframework.core.codec.CodecException; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.http.MediaType; import org.springframework.http.codec.Pojo; import static org.junit.Assert.assertFalse; @@ -50,9 +51,9 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa public void canDecode() { Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(); ResolvableType type = ResolvableType.forClass(Pojo.class); - assertTrue(decoder.canDecode(type, MediaType.APPLICATION_JSON)); + assertTrue(decoder.canDecode(type, APPLICATION_JSON)); assertTrue(decoder.canDecode(type, null)); - assertFalse(decoder.canDecode(type, MediaType.APPLICATION_XML)); + assertFalse(decoder.canDecode(type, APPLICATION_XML)); } @Test @@ -60,12 +61,11 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa Flux source = Flux.just(stringBuffer("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}")); ResolvableType elementType = ResolvableType.forClass(Pojo.class); Flux flux = new Jackson2JsonDecoder().decode(source, elementType, null, - Collections.emptyMap()); + emptyMap()); StepVerifier.create(flux) .expectNext(new Pojo("foofoo", "barbar")) - .expectComplete() - .verify(); + .verifyComplete(); } @Test @@ -73,7 +73,7 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa Flux source = Flux.just(stringBuffer("{\"foo\":}")); ResolvableType elementType = ResolvableType.forClass(Pojo.class); Flux flux = new Jackson2JsonDecoder().decode(source, elementType, null, - Collections.emptyMap()); + emptyMap()); StepVerifier.create(flux).verifyError(CodecException.class); } @@ -85,10 +85,10 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa ResolvableType elementType = ResolvableType.forClassWithGenerics(List.class, Pojo.class); Mono mono = new Jackson2JsonDecoder().decodeToMono(source, elementType, - null, Collections.emptyMap()); + null, emptyMap()); StepVerifier.create(mono) - .expectNext(Arrays.asList(new Pojo("f1", "b1"), new Pojo("f2", "b2"))) + .expectNext(asList(new Pojo("f1", "b1"), new Pojo("f2", "b2"))) .expectComplete() .verify(); } @@ -100,21 +100,20 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa ResolvableType elementType = ResolvableType.forClass(Pojo.class); Flux flux = new Jackson2JsonDecoder().decode(source, elementType, null, - Collections.emptyMap()); + emptyMap()); StepVerifier.create(flux) .expectNext(new Pojo("f1", "b1")) .expectNext(new Pojo("f2", "b2")) - .expectComplete() - .verify(); + .verifyComplete(); } @Test - public void jsonView() throws Exception { + public void fieldLevelJsonView() throws Exception { Flux source = Flux.just( stringBuffer("{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}")); ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class); - Map hints = Collections.singletonMap(Jackson2JsonDecoder.JSON_VIEW_HINT, MyJacksonView1.class); + Map hints = singletonMap(JSON_VIEW_HINT, MyJacksonView1.class); Flux flux = new Jackson2JsonDecoder() .decode(source, elementType, null, hints).cast(JacksonViewBean.class); @@ -124,8 +123,25 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa assertNull(b.getWithView2()); assertNull(b.getWithoutView()); }) - .expectComplete() - .verify(); + .verifyComplete(); + } + + @Test + public void classLevelJsonView() throws Exception { + Flux source = Flux.just(stringBuffer( + "{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}")); + ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class); + Map hints = singletonMap(JSON_VIEW_HINT, MyJacksonView3.class); + Flux flux = new Jackson2JsonDecoder() + .decode(source, elementType, null, hints).cast(JacksonViewBean.class); + + StepVerifier.create(flux) + .consumeNextWith(b -> { + assertNull(b.getWithView1()); + assertNull(b.getWithView2()); + assertTrue(b.getWithoutView().equals("without")); + }) + .verifyComplete(); } @Test @@ -133,54 +149,11 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa Flux source = Flux.empty(); ResolvableType elementType = ResolvableType.forClass(Pojo.class); Mono mono = new Jackson2JsonDecoder().decodeToMono(source, elementType, - null, Collections.emptyMap()); + null, emptyMap()); StepVerifier.create(mono) .expectNextCount(0) - .expectComplete() - .verify(); - } - - - private interface MyJacksonView1 {} - - private interface MyJacksonView2 {} - - - @SuppressWarnings("unused") - private static class JacksonViewBean { - - @JsonView(MyJacksonView1.class) - private String withView1; - - @JsonView(MyJacksonView2.class) - private String withView2; - - private String withoutView; - - public String getWithView1() { - return withView1; - } - - public void setWithView1(String withView1) { - this.withView1 = withView1; - } - - public String getWithView2() { - return withView2; - } - - public void setWithView2(String withView2) { - this.withView2 = withView2; - } - - public String getWithoutView() { - return withoutView; - } - - public void setWithoutView(String withoutView) { - this.withoutView = withoutView; - } + .verifyComplete(); } } 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 972f92e9ea9..6c808311c2a 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 @@ -16,14 +16,16 @@ package org.springframework.http.codec.json; -import java.util.Collections; import java.util.Map; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; -import com.fasterxml.jackson.annotation.JsonView; +import static java.util.Collections.*; import org.junit.Test; +import static org.springframework.http.MediaType.*; import static org.springframework.http.MediaType.APPLICATION_STREAM_JSON; +import static org.springframework.http.codec.json.Jackson2JsonEncoder.*; +import static org.springframework.http.codec.json.JacksonViewBean.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -31,7 +33,6 @@ import reactor.test.StepVerifier; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.http.MediaType; import org.springframework.http.codec.Pojo; import org.springframework.http.codec.ServerSentEvent; @@ -49,11 +50,11 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa @Test public void canEncode() { ResolvableType pojoType = ResolvableType.forClass(Pojo.class); - assertTrue(this.encoder.canEncode(pojoType, MediaType.APPLICATION_JSON)); + assertTrue(this.encoder.canEncode(pojoType, APPLICATION_JSON)); assertTrue(this.encoder.canEncode(pojoType, null)); - assertFalse(this.encoder.canEncode(pojoType, MediaType.APPLICATION_XML)); + assertFalse(this.encoder.canEncode(pojoType, APPLICATION_XML)); ResolvableType sseType = ResolvableType.forClass(ServerSentEvent.class); - assertFalse(this.encoder.canEncode(sseType, MediaType.APPLICATION_JSON)); + assertFalse(this.encoder.canEncode(sseType, APPLICATION_JSON)); } @Test @@ -64,24 +65,22 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa new Pojo("foofoofoo", "barbarbar") ); ResolvableType type = ResolvableType.forClass(Pojo.class); - Flux output = this.encoder.encode(source, this.bufferFactory, type, null, Collections.emptyMap()); + Flux output = this.encoder.encode(source, this.bufferFactory, type, null, emptyMap()); StepVerifier.create(output) .consumeNextWith(stringConsumer("[{\"foo\":\"foo\",\"bar\":\"bar\"},{\"foo\":\"foofoo\",\"bar\":\"barbar\"},{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}]")) - .expectComplete() - .verify(); + .verifyComplete(); } @Test public void encodeWithType() throws Exception { Flux source = Flux.just(new Foo(), new Bar()); ResolvableType type = ResolvableType.forClass(ParentClass.class); - Flux output = this.encoder.encode(source, this.bufferFactory, type, null, Collections.emptyMap()); + Flux output = this.encoder.encode(source, this.bufferFactory, type, null, emptyMap()); StepVerifier.create(output) .consumeNextWith(stringConsumer("[{\"type\":\"foo\"},{\"type\":\"bar\"}]")) - .expectComplete() - .verify(); + .verifyComplete(); } @Test @@ -92,31 +91,45 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa new Pojo("foofoofoo", "barbarbar") ); ResolvableType type = ResolvableType.forClass(Pojo.class); - Flux output = this.encoder.encode(source, this.bufferFactory, type, APPLICATION_STREAM_JSON, Collections.emptyMap()); + Flux output = this.encoder.encode(source, this.bufferFactory, type, APPLICATION_STREAM_JSON, emptyMap()); StepVerifier.create(output) .consumeNextWith(stringConsumer("{\"foo\":\"foo\",\"bar\":\"bar\"}\n")) .consumeNextWith(stringConsumer("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}\n")) .consumeNextWith(stringConsumer("{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}\n")) - .expectComplete() - .verify(); + .verifyComplete(); } @Test - public void jsonView() throws Exception { + public void fieldLevelJsonView() throws Exception { JacksonViewBean bean = new JacksonViewBean(); bean.setWithView1("with"); bean.setWithView2("with"); bean.setWithoutView("without"); ResolvableType type = ResolvableType.forClass(JacksonViewBean.class); - Map hints = Collections.singletonMap(Jackson2JsonEncoder.JSON_VIEW_HINT, MyJacksonView1.class); + Map hints = singletonMap(JSON_VIEW_HINT, MyJacksonView1.class); Flux output = this.encoder.encode(Mono.just(bean), this.bufferFactory, type, null, hints); StepVerifier.create(output) .consumeNextWith(stringConsumer("{\"withView1\":\"with\"}")) - .expectComplete() - .verify(); + .verifyComplete(); + } + + @Test + public void classLevelJsonView() throws Exception { + JacksonViewBean bean = new JacksonViewBean(); + bean.setWithView1("with"); + bean.setWithView2("with"); + bean.setWithoutView("without"); + + ResolvableType type = ResolvableType.forClass(JacksonViewBean.class); + Map hints = singletonMap(JSON_VIEW_HINT, MyJacksonView3.class); + Flux output = this.encoder.encode(Mono.just(bean), this.bufferFactory, type, null, hints); + + StepVerifier.create(output) + .consumeNextWith(stringConsumer("{\"withoutView\":\"without\"}")) + .verifyComplete(); } @@ -132,46 +145,4 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa private static class Bar extends ParentClass { } - - private interface MyJacksonView1 {} - - private interface MyJacksonView2 {} - - - @SuppressWarnings("unused") - private static class JacksonViewBean { - - @JsonView(MyJacksonView1.class) - private String withView1; - - @JsonView(MyJacksonView2.class) - private String withView2; - - private String withoutView; - - public String getWithView1() { - return withView1; - } - - public void setWithView1(String withView1) { - this.withView1 = withView1; - } - - public String getWithView2() { - return withView2; - } - - public void setWithView2(String withView2) { - this.withView2 = withView2; - } - - public String getWithoutView() { - return withoutView; - } - - public void setWithoutView(String withoutView) { - this.withoutView = withoutView; - } - } - } diff --git a/spring-web/src/test/java/org/springframework/http/codec/json/JacksonViewBean.java b/spring-web/src/test/java/org/springframework/http/codec/json/JacksonViewBean.java new file mode 100644 index 00000000000..b70de528773 --- /dev/null +++ b/spring-web/src/test/java/org/springframework/http/codec/json/JacksonViewBean.java @@ -0,0 +1,62 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.http.codec.json; + +import com.fasterxml.jackson.annotation.JsonView; + +/** + * @author Sebastien Deleuze + */ +@JsonView(JacksonViewBean.MyJacksonView3.class) +class JacksonViewBean { + + interface MyJacksonView1 {} + interface MyJacksonView2 {} + interface MyJacksonView3 {} + + @JsonView(MyJacksonView1.class) + private String withView1; + + @JsonView(MyJacksonView2.class) + private String withView2; + + private String withoutView; + + public String getWithView1() { + return withView1; + } + + public void setWithView1(String withView1) { + this.withView1 = withView1; + } + + public String getWithView2() { + return withView2; + } + + public void setWithView2(String withView2) { + this.withView2 = withView2; + } + + public String getWithoutView() { + return withoutView; + } + + public void setWithoutView(String withoutView) { + this.withoutView = withoutView; + } +} diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java index a55bc4027b6..7fcf96bb083 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java @@ -256,7 +256,7 @@ public class MappingJackson2HttpMessageConverterTests { } @Test - public void jsonView() throws Exception { + public void fieldLevelJsonView() throws Exception { MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); JacksonViewBean bean = new JacksonViewBean(); bean.setWithView1("with"); @@ -273,6 +273,24 @@ public class MappingJackson2HttpMessageConverterTests { assertThat(result, not(containsString("\"withoutView\":\"without\""))); } + @Test + public void classLevelJsonView() throws Exception { + MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); + JacksonViewBean bean = new JacksonViewBean(); + bean.setWithView1("with"); + bean.setWithView2("with"); + bean.setWithoutView("without"); + + MappingJacksonValue jacksonValue = new MappingJacksonValue(bean); + jacksonValue.setSerializationView(MyJacksonView3.class); + this.converter.writeInternal(jacksonValue, null, outputMessage); + + String result = outputMessage.getBodyAsString(StandardCharsets.UTF_8); + assertThat(result, not(containsString("\"withView1\":\"with\""))); + assertThat(result, not(containsString("\"withView2\":\"with\""))); + assertThat(result, containsString("\"withoutView\":\"without\"")); + } + @Test public void filters() throws Exception { MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); @@ -449,12 +467,15 @@ public class MappingJackson2HttpMessageConverterTests { } - private interface MyJacksonView1 {}; + private interface MyJacksonView1 {} + + private interface MyJacksonView2 {} - private interface MyJacksonView2 {}; + private interface MyJacksonView3 {} @SuppressWarnings("unused") + @JsonView(MyJacksonView3.class) private static class JacksonViewBean { @JsonView(MyJacksonView1.class)