From 0bc447c3043c284aaac88939ecd349bb9c2b38ee Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 17 Apr 2024 15:39:04 +0100 Subject: [PATCH] Jackson decoder supports array/Collection elements Closes gh-32579 --- .../codec/json/AbstractJackson2Decoder.java | 8 ++++++-- .../codec/json/Jackson2JsonDecoderTests.java | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java index 2cf3fc8b7f..f78d548832 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -19,6 +19,7 @@ package org.springframework.http.codec.json; import java.io.IOException; import java.lang.annotation.Annotation; import java.math.BigDecimal; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -135,9 +136,12 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple forceUseOfBigDecimal = true; } + boolean tokenizeArrays = (!elementType.isArray() && + !Collection.class.isAssignableFrom(elementType.resolve(Object.class))); + Flux processed = processInput(input, elementType, mimeType, hints); Flux tokens = Jackson2Tokenizer.tokenize(processed, mapper.getFactory(), mapper, - true, forceUseOfBigDecimal, getMaxInMemorySize()); + tokenizeArrays, forceUseOfBigDecimal, getMaxInMemorySize()); return Flux.deferContextual(contextView -> { 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 fb90638aee..5991af5ebe 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 @@ -46,6 +46,7 @@ import org.springframework.http.MediaType; import org.springframework.http.codec.json.JacksonViewBean.MyJacksonView1; import org.springframework.http.codec.json.JacksonViewBean.MyJacksonView3; import org.springframework.util.MimeType; +import org.springframework.util.MimeTypeUtils; import org.springframework.web.testfixture.xml.Pojo; import static org.assertj.core.api.Assertions.assertThat; @@ -172,6 +173,22 @@ class Jackson2JsonDecoderTests extends AbstractDecoderTests .verify(), null, null); } + @Test + protected void decodeToFluxWithListElements() { + Flux input = Flux.concat( + stringBuffer("[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]"), + stringBuffer("[{\"bar\":\"b3\",\"foo\":\"f3\"},{\"bar\":\"b4\",\"foo\":\"f4\"}]")); + + ResolvableType elementType = ResolvableType.forClassWithGenerics(List.class, Pojo.class); + + testDecodeAll(input, elementType, + step -> step + .expectNext(List.of(pojo1, pojo2)) + .expectNext(List.of(new Pojo("f3", "b3"), new Pojo("f4", "b4"))) + .verifyComplete(), + MimeTypeUtils.APPLICATION_JSON, + Collections.emptyMap()); + } @Test void decodeEmptyArrayToFlux() {