From 21d61316bef7568069d63b3c41625d6a262bb542 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 16 Mar 2022 07:37:20 +0000 Subject: [PATCH] Unwrap MappingJacksonValue before selecting ObjectMapper See gh-28045 --- .../codec/json/AbstractJackson2Encoder.java | 12 ++++++---- .../codec/json/Jackson2JsonEncoderTests.java | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java index cae80b79f7bb..ffb979f27c4d 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java @@ -196,22 +196,26 @@ public Flux encode(Publisher inputStream, DataBufferFactory buffe public DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory, ResolvableType valueType, @Nullable MimeType mimeType, @Nullable Map hints) { - ObjectMapper mapper = selectObjectMapper(valueType, mimeType); - if (mapper == null) { - throw new IllegalStateException("No ObjectMapper for " + valueType); - } Class jsonView = null; FilterProvider filters = null; if (value instanceof MappingJacksonValue) { MappingJacksonValue container = (MappingJacksonValue) value; value = container.getValue(); + valueType = ResolvableType.forInstance(value); jsonView = container.getSerializationView(); filters = container.getFilters(); } + + ObjectMapper mapper = selectObjectMapper(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); } + ByteArrayBuilder byteBuilder = new ByteArrayBuilder(writer.getFactory()._getBufferRecycler()); try { JsonEncoding encoding = getJsonEncoding(mimeType); 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 3fb276a0264b..2e589ac2a8f8 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 @@ -231,6 +231,29 @@ public void jacksonValue() { ); } + @Test // gh-28045 + public void jacksonValueUnwrappedBeforeObjectMapperSelection() { + + JacksonViewBean bean = new JacksonViewBean(); + bean.setWithView1("with"); + bean.setWithView2("with"); + bean.setWithoutView("without"); + + MappingJacksonValue jacksonValue = new MappingJacksonValue(bean); + jacksonValue.setSerializationView(MyJacksonView1.class); + + ResolvableType type = ResolvableType.forClass(MappingJacksonValue.class); + + MediaType halMediaType = MediaType.parseMediaType("application/hal+json"); + ObjectMapper mapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true); + this.encoder.registerObjectMappersForType(JacksonViewBean.class, map -> map.put(halMediaType, mapper)); + + testEncode(Mono.just(jacksonValue), type, halMediaType, Collections.emptyMap(), step -> step + .consumeNextWith(expectString("{\n \"withView1\" : \"with\"\n}").andThen(DataBufferUtils::release)) + .verifyComplete() + ); + } + @Test // gh-22771 public void encodeWithFlushAfterWriteOff() { ObjectMapper mapper = new ObjectMapper();