Add class level @JsonView tests

Issue: SPR-14925
This commit is contained in:
Sebastien Deleuze 2017-03-22 11:50:41 +01:00
parent 722e23066c
commit 4db2daae5c
4 changed files with 155 additions and 128 deletions

View File

@ -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<DataBuffer> source = Flux.just(stringBuffer("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}"));
ResolvableType elementType = ResolvableType.forClass(Pojo.class);
Flux<Object> 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<DataBuffer> source = Flux.just(stringBuffer("{\"foo\":}"));
ResolvableType elementType = ResolvableType.forClass(Pojo.class);
Flux<Object> 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<Object> 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<Object> 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<DataBuffer> source = Flux.just(
stringBuffer("{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}"));
ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class);
Map<String, Object> hints = Collections.singletonMap(Jackson2JsonDecoder.JSON_VIEW_HINT, MyJacksonView1.class);
Map<String, Object> hints = singletonMap(JSON_VIEW_HINT, MyJacksonView1.class);
Flux<JacksonViewBean> 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<DataBuffer> source = Flux.just(stringBuffer(
"{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}"));
ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class);
Map<String, Object> hints = singletonMap(JSON_VIEW_HINT, MyJacksonView3.class);
Flux<JacksonViewBean> 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<DataBuffer> source = Flux.empty();
ResolvableType elementType = ResolvableType.forClass(Pojo.class);
Mono<Object> 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();
}
}

View File

@ -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<DataBuffer> output = this.encoder.encode(source, this.bufferFactory, type, null, Collections.emptyMap());
Flux<DataBuffer> 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<ParentClass> source = Flux.just(new Foo(), new Bar());
ResolvableType type = ResolvableType.forClass(ParentClass.class);
Flux<DataBuffer> output = this.encoder.encode(source, this.bufferFactory, type, null, Collections.emptyMap());
Flux<DataBuffer> 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<DataBuffer> output = this.encoder.encode(source, this.bufferFactory, type, APPLICATION_STREAM_JSON, Collections.emptyMap());
Flux<DataBuffer> 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<String, Object> hints = Collections.singletonMap(Jackson2JsonEncoder.JSON_VIEW_HINT, MyJacksonView1.class);
Map<String, Object> hints = singletonMap(JSON_VIEW_HINT, MyJacksonView1.class);
Flux<DataBuffer> 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<String, Object> hints = singletonMap(JSON_VIEW_HINT, MyJacksonView3.class);
Flux<DataBuffer> 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;
}
}
}

View File

@ -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;
}
}

View File

@ -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)