mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-22 22:19:03 +00:00
Fix FilterProvider handling in AbstractJacksonEncoder
Closes gh-35575
This commit is contained in:
+10
-14
@@ -161,7 +161,7 @@ public abstract class AbstractJacksonEncoder<T extends ObjectMapper> extends Jac
|
||||
throw new IllegalStateException("No ObjectMapper for " + elementType);
|
||||
}
|
||||
|
||||
ObjectWriter writer = createObjectWriter(mapper, elementType, mimeType, null, hintsToUse);
|
||||
ObjectWriter writer = createObjectWriter(mapper, elementType, mimeType, hintsToUse);
|
||||
ByteArrayBuilder byteBuilder = new ByteArrayBuilder(writer.generatorFactory()._getBufferRecycler());
|
||||
JsonEncoding encoding = getJsonEncoding(mimeType);
|
||||
JsonGenerator generator = mapper.createGenerator(byteBuilder, encoding);
|
||||
@@ -219,22 +219,12 @@ public abstract class AbstractJacksonEncoder<T extends ObjectMapper> extends Jac
|
||||
public DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory,
|
||||
ResolvableType valueType, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
Class<?> jsonView = null;
|
||||
FilterProvider filters = null;
|
||||
if (hints != null) {
|
||||
jsonView = (Class<?>) hints.get(JSON_VIEW_HINT);
|
||||
filters = (FilterProvider) hints.get(FILTER_PROVIDER_HINT);
|
||||
}
|
||||
|
||||
T mapper = selectMapper(valueType, mimeType);
|
||||
if (mapper == null) {
|
||||
throw new IllegalStateException("No ObjectMapper for " + valueType);
|
||||
}
|
||||
|
||||
ObjectWriter writer = createObjectWriter(mapper, valueType, mimeType, jsonView, hints);
|
||||
if (filters != null) {
|
||||
writer = writer.with(filters);
|
||||
}
|
||||
ObjectWriter writer = createObjectWriter(mapper, valueType, mimeType, hints);
|
||||
|
||||
ByteArrayBuilder byteBuilder = new ByteArrayBuilder(writer.generatorFactory()._getBufferRecycler());
|
||||
try {
|
||||
@@ -321,13 +311,19 @@ public abstract class AbstractJacksonEncoder<T extends ObjectMapper> extends Jac
|
||||
|
||||
private ObjectWriter createObjectWriter(
|
||||
T mapper, ResolvableType valueType, @Nullable MimeType mimeType,
|
||||
@Nullable Class<?> jsonView, @Nullable Map<String, Object> hints) {
|
||||
@Nullable Map<String, Object> hints) {
|
||||
|
||||
JavaType javaType = getJavaType(valueType.getType(), null);
|
||||
if (jsonView == null && hints != null) {
|
||||
Class<?> jsonView = null;
|
||||
FilterProvider filters = null;
|
||||
if (hints != null) {
|
||||
jsonView = (Class<?>) hints.get(JacksonCodecSupport.JSON_VIEW_HINT);
|
||||
filters = (FilterProvider) hints.get(FILTER_PROVIDER_HINT);
|
||||
}
|
||||
ObjectWriter writer = (jsonView != null ? mapper.writerWithView(jsonView) : mapper.writer());
|
||||
if (filters != null) {
|
||||
writer = writer.with(filters);
|
||||
}
|
||||
if (javaType.isContainerType()) {
|
||||
writer = writer.forType(javaType);
|
||||
}
|
||||
|
||||
+54
@@ -22,6 +22,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFilter;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -30,6 +31,9 @@ import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import tools.jackson.databind.SerializationFeature;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
import tools.jackson.databind.ser.FilterProvider;
|
||||
import tools.jackson.databind.ser.std.SimpleBeanPropertyFilter;
|
||||
import tools.jackson.databind.ser.std.SimpleFilterProvider;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
@@ -50,6 +54,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON;
|
||||
import static org.springframework.http.MediaType.APPLICATION_NDJSON;
|
||||
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM;
|
||||
import static org.springframework.http.MediaType.APPLICATION_XML;
|
||||
import static org.springframework.http.codec.JacksonCodecSupport.FILTER_PROVIDER_HINT;
|
||||
import static org.springframework.http.codec.JacksonCodecSupport.JSON_VIEW_HINT;
|
||||
|
||||
/**
|
||||
@@ -211,6 +216,24 @@ class JacksonJsonEncoderTests extends AbstractEncoderTests<JacksonJsonEncoder> {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void fieldLevelJsonViewStream() {
|
||||
JacksonViewBean bean = new JacksonViewBean();
|
||||
bean.setWithView1("with");
|
||||
bean.setWithView2("with");
|
||||
bean.setWithoutView("without");
|
||||
Flux<JacksonViewBean> input = Flux.just(bean, bean);
|
||||
|
||||
ResolvableType type = ResolvableType.forClass(JacksonViewBean.class);
|
||||
Map<String, Object> hints = singletonMap(JSON_VIEW_HINT, MyJacksonView1.class);
|
||||
|
||||
testEncodeAll(input, type, APPLICATION_NDJSON, hints, step -> step
|
||||
.consumeNextWith(expectString("{\"withView1\":\"with\"}\n"))
|
||||
.consumeNextWith(expectString("{\"withView1\":\"with\"}\n"))
|
||||
.verifyComplete()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void classLevelJsonView() {
|
||||
JacksonViewBean bean = new JacksonViewBean();
|
||||
@@ -228,6 +251,33 @@ class JacksonJsonEncoderTests extends AbstractEncoderTests<JacksonJsonEncoder> {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterProvider() {
|
||||
JacksonFilteredBean filteredBean = new JacksonFilteredBean("foo", "bar");
|
||||
FilterProvider filters = new SimpleFilterProvider().addFilter("myJacksonFilter",
|
||||
SimpleBeanPropertyFilter.serializeAllExcept("property2"));
|
||||
Mono<JacksonFilteredBean> input = Mono.just(filteredBean);
|
||||
Map<String, Object> hints = singletonMap(FILTER_PROVIDER_HINT, filters);
|
||||
testEncode(input, ResolvableType.forClass(Pojo.class), APPLICATION_JSON, hints, step -> step
|
||||
.consumeNextWith(expectString("{\"property1\":\"foo\"}"))
|
||||
.verifyComplete()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterProviderStream() {
|
||||
JacksonFilteredBean filteredBean = new JacksonFilteredBean("foo", "bar");
|
||||
FilterProvider filters = new SimpleFilterProvider().addFilter("myJacksonFilter",
|
||||
SimpleBeanPropertyFilter.serializeAllExcept("property2"));
|
||||
Flux<JacksonFilteredBean> input = Flux.just(filteredBean, filteredBean);
|
||||
Map<String, Object> hints = singletonMap(FILTER_PROVIDER_HINT, filters);
|
||||
testEncodeAll(input, ResolvableType.forClass(Pojo.class), APPLICATION_NDJSON, hints, step -> step
|
||||
.consumeNextWith(expectString("{\"property1\":\"foo\"}\n"))
|
||||
.consumeNextWith(expectString("{\"property1\":\"foo\"}\n"))
|
||||
.verifyComplete()
|
||||
);
|
||||
}
|
||||
|
||||
@Test // gh-22771
|
||||
public void encodeWithFlushAfterWriteOff() {
|
||||
JsonMapper mapper = JsonMapper.builder().configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, false).build();
|
||||
@@ -267,4 +317,8 @@ class JacksonJsonEncoderTests extends AbstractEncoderTests<JacksonJsonEncoder> {
|
||||
private static class Bar extends ParentClass {
|
||||
}
|
||||
|
||||
@JsonFilter("myJacksonFilter")
|
||||
record JacksonFilteredBean(String property1, String property2) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user