Improve support for generics in Jackson codecs
Closes gh-23791
This commit is contained in:
parent
77517d6cff
commit
992e75303d
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -153,8 +153,10 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
|
|||
|
||||
private ObjectReader getObjectReader(ResolvableType elementType, @Nullable Map<String, Object> hints) {
|
||||
Assert.notNull(elementType, "'elementType' must not be null");
|
||||
MethodParameter param = getParameter(elementType);
|
||||
Class<?> contextClass = (param != null ? param.getContainingClass() : null);
|
||||
Class<?> contextClass = getContextClass(elementType);
|
||||
if (contextClass == null && hints != null) {
|
||||
contextClass = getContextClass((ResolvableType) hints.get(ACTUAL_TYPE_HINT));
|
||||
}
|
||||
JavaType javaType = getJavaType(elementType.getType(), contextClass);
|
||||
Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
|
||||
return jsonView != null ?
|
||||
|
@ -162,6 +164,12 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
|
|||
getObjectMapper().readerFor(javaType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Class<?> getContextClass(@Nullable ResolvableType elementType) {
|
||||
MethodParameter param = (elementType != null ? getParameter(elementType) : null);
|
||||
return (param != null ? param.getContainingClass() : null);
|
||||
}
|
||||
|
||||
private void logValue(@Nullable Object value, @Nullable Map<String, Object> hints) {
|
||||
if (!Hints.isLoggingSuppressed(hints)) {
|
||||
LogFormatUtils.traceDebug(logger, traceOn -> {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -20,6 +20,7 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -34,6 +35,8 @@ import org.springframework.core.MethodParameter;
|
|||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.http.HttpLogging;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
|
@ -55,6 +58,15 @@ public abstract class Jackson2CodecSupport {
|
|||
*/
|
||||
public static final String JSON_VIEW_HINT = Jackson2CodecSupport.class.getName() + ".jsonView";
|
||||
|
||||
/**
|
||||
* The key for the hint to access the actual ResolvableType passed into
|
||||
* {@link org.springframework.http.codec.HttpMessageReader#read(ResolvableType, ResolvableType, ServerHttpRequest, ServerHttpResponse, Map)}
|
||||
* (server-side only). Currently set when the method argument has generics because
|
||||
* in case of reactive types, use of {@code ResolvableType.getGeneric()} means no
|
||||
* MethodParameter source and no knowledge of the containing class.
|
||||
*/
|
||||
static final String ACTUAL_TYPE_HINT = Jackson2CodecSupport.class.getName() + ".actualType";
|
||||
|
||||
private static final String JSON_VIEW_HINT_ERROR =
|
||||
"@JsonView only supported for write hints with exactly 1 class argument: ";
|
||||
|
||||
|
@ -106,11 +118,20 @@ public abstract class Jackson2CodecSupport {
|
|||
protected Map<String, Object> getHints(ResolvableType resolvableType) {
|
||||
MethodParameter param = getParameter(resolvableType);
|
||||
if (param != null) {
|
||||
Map<String, Object> hints = null;
|
||||
if (resolvableType.hasGenerics()) {
|
||||
hints = new HashMap<>(2);
|
||||
hints.put(ACTUAL_TYPE_HINT, resolvableType);
|
||||
}
|
||||
JsonView annotation = getAnnotation(param, JsonView.class);
|
||||
if (annotation != null) {
|
||||
Class<?>[] classes = annotation.value();
|
||||
Assert.isTrue(classes.length == 1, JSON_VIEW_HINT_ERROR + param);
|
||||
return Hints.from(JSON_VIEW_HINT, classes[0]);
|
||||
hints = (hints != null ? hints : new HashMap<>(1));
|
||||
hints.put(JSON_VIEW_HINT, classes[0]);
|
||||
}
|
||||
if (hints != null) {
|
||||
return hints;
|
||||
}
|
||||
}
|
||||
return Hints.none();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -28,7 +28,6 @@ import javax.xml.bind.annotation.XmlRootElement;
|
|||
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Maybe;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
@ -522,7 +521,6 @@ public class RequestMappingMessageConversionIntegrationTests extends AbstractReq
|
|||
assertThat(getApplicationContext().getBean(PersonCreateController.class).persons.size()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@ParameterizedHttpServerTest // gh-23791
|
||||
public void personCreateViaDefaultMethodWithGenerics(HttpServer httpServer) throws Exception {
|
||||
startServer(httpServer);
|
||||
|
|
Loading…
Reference in New Issue