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