Skip to content

Commit 57067f5

Browse files
committed
Polishing contribution
Closes gh-28401
1 parent c2f1ddc commit 57067f5

File tree

5 files changed

+175
-231
lines changed

5 files changed

+175
-231
lines changed

spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java

+55-79
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
import org.reactivestreams.Publisher;
3434
import reactor.core.publisher.Flux;
3535
import reactor.core.publisher.Mono;
36+
import reactor.util.context.ContextView;
3637

3738
import org.springframework.core.MethodParameter;
3839
import org.springframework.core.ResolvableType;
@@ -46,7 +47,6 @@
4647
import org.springframework.http.codec.HttpMessageDecoder;
4748
import org.springframework.http.server.reactive.ServerHttpRequest;
4849
import org.springframework.http.server.reactive.ServerHttpResponse;
49-
import org.springframework.lang.NonNull;
5050
import org.springframework.lang.Nullable;
5151
import org.springframework.util.Assert;
5252
import org.springframework.util.MimeType;
@@ -139,22 +139,26 @@ public Flux<Object> decode(Publisher<DataBuffer> input, ResolvableType elementTy
139139
Flux<TokenBuffer> tokens = Jackson2Tokenizer.tokenize(processed, mapper.getFactory(), mapper,
140140
true, forceUseOfBigDecimal, getMaxInMemorySize());
141141

142-
ObjectReader objectReader = getObjectReader(mapper, elementType, hints);
143-
144-
return customizeReaderFromStream(objectReader, mimeType, elementType, hints)
145-
.flatMapMany(reader -> tokens.handle((tokenBuffer, sink) -> {
146-
try {
147-
Object value = reader.readValue(tokenBuffer.asParser(mapper));
148-
logValue(value, hints);
149-
if (value != null) {
150-
sink.next(value);
151-
}
152-
}
153-
catch (IOException ex) {
154-
sink.error(processException(ex));
155-
}
156-
})
157-
);
142+
return Flux.deferContextual(contextView -> {
143+
144+
Map<String, Object> hintsToUse = contextView.isEmpty() ? hints :
145+
Hints.merge(hints, ContextView.class.getName(), contextView);
146+
147+
ObjectReader reader = createObjectReader(mapper, elementType, hintsToUse);
148+
149+
return tokens.handle((tokenBuffer, sink) -> {
150+
try {
151+
Object value = reader.readValue(tokenBuffer.asParser(mapper));
152+
logValue(value, hints);
153+
if (value != null) {
154+
sink.next(value);
155+
}
156+
}
157+
catch (IOException ex) {
158+
sink.error(processException(ex));
159+
}
160+
});
161+
});
158162
}
159163

160164
/**
@@ -169,45 +173,36 @@ public Flux<Object> decode(Publisher<DataBuffer> input, ResolvableType elementTy
169173
* @since 5.1.14
170174
*/
171175
protected Flux<DataBuffer> processInput(Publisher<DataBuffer> input, ResolvableType elementType,
172-
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
176+
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
173177

174178
return Flux.from(input);
175179
}
176180

177181
@Override
178182
public Mono<Object> decodeToMono(Publisher<DataBuffer> input, ResolvableType elementType,
179183
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
180-
return DataBufferUtils.join(input, this.maxInMemorySize)
181-
.flatMap(dataBuffer -> {
182-
try {
183-
ObjectReader objectReader = getObjectReader(elementType, mimeType, hints);
184-
return customizeReaderFromStream(objectReader, mimeType, elementType, hints)
185-
.flatMap(reader -> {
186-
try {
187-
return Mono.justOrEmpty(decode(dataBuffer, reader, hints));
188-
}
189-
catch (DecodingException ex) {
190-
return Mono.error(ex);
191-
}
192-
});
193-
}
194-
catch (IllegalStateException ex) {
195-
return Mono.error(ex);
196-
}
197-
});
184+
185+
return Mono.deferContextual(contextView -> {
186+
187+
Map<String, Object> hintsToUse = contextView.isEmpty() ? hints :
188+
Hints.merge(hints, ContextView.class.getName(), contextView);
189+
190+
return DataBufferUtils.join(input, this.maxInMemorySize).flatMap(dataBuffer ->
191+
Mono.justOrEmpty(decode(dataBuffer, elementType, mimeType, hintsToUse)));
192+
});
198193
}
199194

200195
@Override
201196
public Object decode(DataBuffer dataBuffer, ResolvableType targetType,
202197
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) throws DecodingException {
203-
ObjectReader reader = getObjectReader(targetType, mimeType, hints);
204-
reader = customizeReader(reader, mimeType, targetType, hints);
205-
return decode(dataBuffer, reader, hints);
206-
}
207198

208-
private Object decode(@NonNull DataBuffer dataBuffer, @NonNull ObjectReader objectReader,
209-
@Nullable Map<String, Object> hints) throws DecodingException {
199+
ObjectMapper mapper = selectObjectMapper(targetType, mimeType);
200+
if (mapper == null) {
201+
throw new IllegalStateException("No ObjectMapper for " + targetType);
202+
}
203+
210204
try {
205+
ObjectReader objectReader = createObjectReader(mapper, targetType, hints);
211206
Object value = objectReader.readValue(dataBuffer.asInputStream());
212207
logValue(value, hints);
213208
return value;
@@ -220,16 +215,7 @@ private Object decode(@NonNull DataBuffer dataBuffer, @NonNull ObjectReader obje
220215
}
221216
}
222217

223-
private ObjectReader getObjectReader(ResolvableType targetType, @Nullable MimeType mimeType,
224-
@Nullable Map<String, Object> hints) {
225-
ObjectMapper mapper = selectObjectMapper(targetType, mimeType);
226-
if (mapper == null) {
227-
throw new IllegalStateException("No ObjectMapper for " + targetType);
228-
}
229-
return getObjectReader(mapper, targetType, hints);
230-
}
231-
232-
private ObjectReader getObjectReader(
218+
private ObjectReader createObjectReader(
233219
ObjectMapper mapper, ResolvableType elementType, @Nullable Map<String, Object> hints) {
234220

235221
Assert.notNull(elementType, "'elementType' must not be null");
@@ -239,34 +225,28 @@ private ObjectReader getObjectReader(
239225
}
240226
JavaType javaType = getJavaType(elementType.getType(), contextClass);
241227
Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
242-
return jsonView != null ?
228+
229+
ObjectReader objectReader = (jsonView != null ?
243230
mapper.readerWithView(jsonView).forType(javaType) :
244-
mapper.readerFor(javaType);
245-
}
231+
mapper.readerFor(javaType));
246232

247-
/**
248-
* Provides the ability for subclasses to customize the {@link ObjectReader} for deserialization from a stream.
249-
* @param reader the {@link ObjectReader} available for customization
250-
* @param mimeType the MIME type associated with the input stream
251-
* @param elementType the expected type of elements in the output stream
252-
* @param hints additional information about how to do encode
253-
* @return the customized {@link ObjectReader}
254-
*/
255-
protected Mono<ObjectReader> customizeReaderFromStream(@NonNull ObjectReader reader, @Nullable MimeType mimeType,
256-
ResolvableType elementType, @Nullable Map<String, Object> hints) {
257-
return Mono.just(customizeReader(reader, mimeType, elementType, hints));
233+
return customizeReader(objectReader, elementType, hints);
258234
}
259235

260236
/**
261-
* Provides the ability for subclasses to customize the {@link ObjectReader} for deserialization.
262-
* @param reader the {@link ObjectReader} available for customization
263-
* @param mimeType the MIME type associated with the input stream
264-
* @param elementType the expected type of elements in the output stream
265-
* @param hints additional information about how to do encode
266-
* @return the customized {@link ObjectReader}
237+
* Subclasses can use this method to customize {@link ObjectReader} used
238+
* for reading values.
239+
* @param reader the reader instance to customize
240+
* @param elementType the target type of element values to read to
241+
* @param hints a map with serialization hints;
242+
* the Reactor Context, when available, may be accessed under the key
243+
* {@code ContextView.class.getName()}
244+
* @return the customized {@code ObjectReader} to use
245+
* @since 6.0
267246
*/
268-
protected ObjectReader customizeReader(@NonNull ObjectReader reader, @Nullable MimeType mimeType,
269-
ResolvableType elementType, @Nullable Map<String, Object> hints) {
247+
protected ObjectReader customizeReader(
248+
ObjectReader reader, ResolvableType elementType, @Nullable Map<String, Object> hints) {
249+
270250
return reader;
271251
}
272252

@@ -312,10 +292,6 @@ public List<MimeType> getDecodableMimeTypes() {
312292
return getMimeTypes();
313293
}
314294

315-
@Override
316-
public List<MimeType> getDecodableMimeTypes(ResolvableType targetType) {
317-
return getMimeTypes(targetType);
318-
}
319295

320296
// Jackson2CodecSupport
321297

0 commit comments

Comments
 (0)