MIME types by Class for Encoder, Decoder, HttpMessageReader|Writer
Closes gh-26212
This commit is contained in:
parent
7cdaaa22bd
commit
0d16c9100a
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.core.codec;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
|
@ -59,7 +60,7 @@ public interface Decoder<T> {
|
|||
* this type must have been previously passed to the {@link #canDecode}
|
||||
* method and it must have returned {@code true}.
|
||||
* @param mimeType the MIME type associated with the input stream (optional)
|
||||
* @param hints additional information about how to do encode
|
||||
* @param hints additional information about how to do decode
|
||||
* @return the output stream with decoded elements
|
||||
*/
|
||||
Flux<T> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
|
||||
|
|
@ -72,7 +73,7 @@ public interface Decoder<T> {
|
|||
* this type must have been previously passed to the {@link #canDecode}
|
||||
* method and it must have returned {@code true}.
|
||||
* @param mimeType the MIME type associated with the input stream (optional)
|
||||
* @param hints additional information about how to do encode
|
||||
* @param hints additional information about how to do decode
|
||||
* @return the output stream with the decoded element
|
||||
*/
|
||||
Mono<T> decodeToMono(Publisher<DataBuffer> inputStream, ResolvableType elementType,
|
||||
|
|
@ -85,7 +86,7 @@ public interface Decoder<T> {
|
|||
* @param buffer the {@code DataBuffer} to decode
|
||||
* @param targetType the expected output type
|
||||
* @param mimeType the MIME type associated with the data
|
||||
* @param hints additional information about how to do encode
|
||||
* @param hints additional information about how to do decode
|
||||
* @return the decoded value, possibly {@code null}
|
||||
* @since 5.2
|
||||
*/
|
||||
|
|
@ -111,8 +112,27 @@ public interface Decoder<T> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the list of MIME types this decoder supports.
|
||||
* Return the list of MIME types supported by this Decoder. The list may not
|
||||
* apply to every possible target element type and calls to this method
|
||||
* should typically be guarded via {@link #canDecode(ResolvableType, MimeType)
|
||||
* canDecode(elementType, null)}. The list may also exclude MIME types
|
||||
* supported only for a specific element type. Alternatively, use
|
||||
* {@link #getDecodableMimeTypes(ResolvableType)} for a more precise list.
|
||||
* @return the list of supported MIME types
|
||||
*/
|
||||
List<MimeType> getDecodableMimeTypes();
|
||||
|
||||
/**
|
||||
* Return the list of MIME types supported by this Decoder for the given type
|
||||
* of element. This list may differ from {@link #getDecodableMimeTypes()}
|
||||
* if the Decoder doesn't support the given element type or if it supports
|
||||
* it only for a subset of MIME types.
|
||||
* @param targetType the type of element to check for decoding
|
||||
* @return the list of MIME types supported for the given target type
|
||||
* @since 5.3.4
|
||||
*/
|
||||
default List<MimeType> getDecodableMimeTypes(ResolvableType targetType) {
|
||||
return (canDecode(targetType, null) ? getDecodableMimeTypes() : Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.core.codec;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -90,8 +91,27 @@ public interface Encoder<T> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the list of mime types this encoder supports.
|
||||
* Return the list of MIME types supported by this Encoder. The list may not
|
||||
* apply to every possible target element type and calls to this method should
|
||||
* typically be guarded via {@link #canEncode(ResolvableType, MimeType)
|
||||
* canEncode(elementType, null)}. The list may also exclude MIME types
|
||||
* supported only for a specific element type. Alternatively, use
|
||||
* {@link #getEncodableMimeTypes(ResolvableType)} for a more precise list.
|
||||
* @return the list of supported MIME types
|
||||
*/
|
||||
List<MimeType> getEncodableMimeTypes();
|
||||
|
||||
/**
|
||||
* Return the list of MIME types supported by this Encoder for the given type
|
||||
* of element. This list may differ from the {@link #getEncodableMimeTypes()}
|
||||
* if the Encoder doesn't support the element type or if it supports it only
|
||||
* for a subset of MIME types.
|
||||
* @param elementType the type of element to check for encoding
|
||||
* @return the list of MIME types supported for the given element type
|
||||
* @since 5.3.4
|
||||
*/
|
||||
default List<MimeType> getEncodableMimeTypes(ResolvableType elementType) {
|
||||
return (canEncode(elementType, null) ? getEncodableMimeTypes() : Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -87,6 +87,10 @@ public class DecoderHttpMessageReader<T> implements HttpMessageReader<T> {
|
|||
return this.mediaTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getReadableMediaTypes(ResolvableType elementType) {
|
||||
return MediaType.asMediaTypes(this.decoder.getDecodableMimeTypes(elementType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -105,6 +105,10 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
|
|||
return this.mediaTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getWritableMediaTypes(ResolvableType elementType) {
|
||||
return MediaType.asMediaTypes(getEncoder().getEncodableMimeTypes(elementType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(ResolvableType elementType, @Nullable MediaType mediaType) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.http.codec;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -43,10 +44,29 @@ import org.springframework.lang.Nullable;
|
|||
public interface HttpMessageReader<T> {
|
||||
|
||||
/**
|
||||
* Return the {@link MediaType}'s that this reader supports.
|
||||
* Return the list of media types supported by this reader. The list may not
|
||||
* apply to every possible target element type and calls to this method
|
||||
* should typically be guarded via {@link #canRead(ResolvableType, MediaType)
|
||||
* canWrite(elementType, null)}. The list may also exclude media types
|
||||
* supported only for a specific element type. Alternatively, use
|
||||
* {@link #getReadableMediaTypes(ResolvableType)} for a more precise list.
|
||||
* @return the general list of supported media types
|
||||
*/
|
||||
List<MediaType> getReadableMediaTypes();
|
||||
|
||||
/**
|
||||
* Return the list of media types supported by this Reader for the given type
|
||||
* of element. This list may differ from {@link #getReadableMediaTypes()}
|
||||
* if the Reader doesn't support the element type, or if it supports it
|
||||
* only for a subset of media types.
|
||||
* @param elementType the type of element to read
|
||||
* @return the list of media types supported for the given class
|
||||
* @since 5.3.4
|
||||
*/
|
||||
default List<MediaType> getReadableMediaTypes(ResolvableType elementType) {
|
||||
return (canRead(elementType, null) ? getReadableMediaTypes() : Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given object type is supported by this reader.
|
||||
* @param elementType the type of object to check
|
||||
|
|
@ -56,7 +76,7 @@ public interface HttpMessageReader<T> {
|
|||
boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType);
|
||||
|
||||
/**
|
||||
* Read from the input message and encode to a stream of objects.
|
||||
* Read from the input message and decode to a stream of objects.
|
||||
* @param elementType the type of objects in the stream which must have been
|
||||
* previously checked via {@link #canRead(ResolvableType, MediaType)}
|
||||
* @param message the message to read from
|
||||
|
|
@ -66,7 +86,7 @@ public interface HttpMessageReader<T> {
|
|||
Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
|
||||
|
||||
/**
|
||||
* Read from the input message and encode to a single object.
|
||||
* Read from the input message and decode to a single object.
|
||||
* @param elementType the type of objects in the stream which must have been
|
||||
* previously checked via {@link #canRead(ResolvableType, MediaType)}
|
||||
* @param message the message to read from
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.http.codec;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -43,10 +44,29 @@ import org.springframework.lang.Nullable;
|
|||
public interface HttpMessageWriter<T> {
|
||||
|
||||
/**
|
||||
* Return the {@link MediaType}'s that this writer supports.
|
||||
* Return the list of media types supported by this Writer. The list may not
|
||||
* apply to every possible target element type and calls to this method should
|
||||
* typically be guarded via {@link #canWrite(ResolvableType, MediaType)
|
||||
* canWrite(elementType, null)}. The list may also exclude media types
|
||||
* supported only for a specific element type. Alternatively, use
|
||||
* {@link #getWritableMediaTypes(ResolvableType)} for a more precise list.
|
||||
* @return the general list of supported media types
|
||||
*/
|
||||
List<MediaType> getWritableMediaTypes();
|
||||
|
||||
/**
|
||||
* Return the list of media types supported by this Writer for the given type
|
||||
* of element. This list may differ from {@link #getWritableMediaTypes()}
|
||||
* if the Writer doesn't support the element type, or if it supports it
|
||||
* only for a subset of media types.
|
||||
* @param elementType the type of element to encode
|
||||
* @return the list of media types supported for the given class
|
||||
* @since 5.3.4
|
||||
*/
|
||||
default List<MediaType> getWritableMediaTypes(ResolvableType elementType) {
|
||||
return (canWrite(elementType, null) ? getWritableMediaTypes() : Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given object type is supported by this writer.
|
||||
* @param elementType the type of object to check
|
||||
|
|
|
|||
|
|
@ -259,6 +259,10 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
|
|||
return getMimeTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimeType> getDecodableMimeTypes(ResolvableType targetType) {
|
||||
return getMimeTypes(targetType);
|
||||
}
|
||||
|
||||
// Jackson2CodecSupport
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -357,6 +357,11 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
|
|||
return getMimeTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimeType> getEncodableMimeTypes(ResolvableType elementType) {
|
||||
return getMimeTypes(elementType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getStreamingMediaTypes() {
|
||||
return Collections.unmodifiableList(this.streamingMediaTypes);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -18,6 +18,7 @@ package org.springframework.http.codec.json;
|
|||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -148,7 +149,7 @@ public abstract class Jackson2CodecSupport {
|
|||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
private Map<Class<?>, Map<MimeType, ObjectMapper>> getObjectMapperRegistrations() {
|
||||
protected Map<Class<?>, Map<MimeType, ObjectMapper>> getObjectMapperRegistrations() {
|
||||
return (this.objectMapperRegistrations != null ? this.objectMapperRegistrations : Collections.emptyMap());
|
||||
}
|
||||
|
||||
|
|
@ -159,6 +160,17 @@ public abstract class Jackson2CodecSupport {
|
|||
return this.mimeTypes;
|
||||
}
|
||||
|
||||
protected List<MimeType> getMimeTypes(ResolvableType elementType) {
|
||||
Class<?> elementClass = elementType.toClass();
|
||||
List<MimeType> result = null;
|
||||
for (Map.Entry<Class<?>, Map<MimeType, ObjectMapper>> entry : getObjectMapperRegistrations().entrySet()) {
|
||||
if (entry.getKey().isAssignableFrom(elementClass)) {
|
||||
result = (result != null ? result : new ArrayList<>(entry.getValue().size()));
|
||||
result.addAll(entry.getValue().keySet());
|
||||
}
|
||||
}
|
||||
return (CollectionUtils.isEmpty(result) ? getMimeTypes() : result);
|
||||
}
|
||||
|
||||
protected boolean supportsMimeType(@Nullable MimeType mimeType) {
|
||||
if (mimeType == null) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -196,7 +196,7 @@ public abstract class BodyExtractors {
|
|||
.map(readerFunction)
|
||||
.orElseGet(() -> {
|
||||
List<MediaType> mediaTypes = context.messageReaders().stream()
|
||||
.flatMap(reader -> reader.getReadableMediaTypes().stream())
|
||||
.flatMap(reader -> reader.getReadableMediaTypes(elementType).stream())
|
||||
.collect(Collectors.toList());
|
||||
return errorFunction.apply(
|
||||
new UnsupportedMediaTypeException(contentType, mediaTypes, elementType));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -385,7 +385,7 @@ public abstract class BodyInserters {
|
|||
BodyInserter.Context context, @Nullable MediaType mediaType) {
|
||||
|
||||
List<MediaType> supportedMediaTypes = context.messageWriters().stream()
|
||||
.flatMap(reader -> reader.getWritableMediaTypes().stream())
|
||||
.flatMap(reader -> reader.getWritableMediaTypes(bodyType).stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new UnsupportedMediaTypeException(mediaType, supportedMediaTypes, bodyType);
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@
|
|||
package org.springframework.web.reactive.result.method.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
|
@ -76,8 +76,6 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
|
|||
|
||||
private final List<HttpMessageReader<?>> messageReaders;
|
||||
|
||||
private final List<MediaType> supportedMediaTypes;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor with {@link HttpMessageReader}'s and a {@link Validator}.
|
||||
|
|
@ -99,9 +97,6 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
|
|||
Assert.notEmpty(messageReaders, "At least one HttpMessageReader is required");
|
||||
Assert.notNull(adapterRegistry, "ReactiveAdapterRegistry is required");
|
||||
this.messageReaders = messageReaders;
|
||||
this.supportedMediaTypes = messageReaders.stream()
|
||||
.flatMap(converter -> converter.getReadableMediaTypes().stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -212,8 +207,9 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
|
|||
if (contentType == null && method != null && SUPPORTED_METHODS.contains(method)) {
|
||||
Flux<DataBuffer> body = request.getBody().doOnNext(buffer -> {
|
||||
DataBufferUtils.release(buffer);
|
||||
// Body not empty, back to 415..
|
||||
throw new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType);
|
||||
// Body not empty, back toy 415..
|
||||
throw new UnsupportedMediaTypeStatusException(
|
||||
mediaType, getSupportedMediaTypes(elementType), elementType);
|
||||
});
|
||||
if (isBodyRequired) {
|
||||
body = body.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
|
||||
|
|
@ -221,7 +217,8 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
|
|||
return (adapter != null ? Mono.just(adapter.fromPublisher(body)) : Mono.from(body));
|
||||
}
|
||||
|
||||
return Mono.error(new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType));
|
||||
return Mono.error(new UnsupportedMediaTypeStatusException(
|
||||
mediaType, getSupportedMediaTypes(elementType), elementType));
|
||||
}
|
||||
|
||||
private Throwable handleReadError(MethodParameter parameter, Throwable ex) {
|
||||
|
|
@ -263,4 +260,12 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
|
|||
}
|
||||
}
|
||||
|
||||
private List<MediaType> getSupportedMediaTypes(ResolvableType elementType) {
|
||||
List<MediaType> mediaTypes = new ArrayList<>();
|
||||
for (HttpMessageReader<?> reader : this.messageReaders) {
|
||||
mediaTypes.addAll(reader.getReadableMediaTypes(elementType));
|
||||
}
|
||||
return mediaTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -192,7 +192,7 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa
|
|||
List<MediaType> writableMediaTypes = new ArrayList<>();
|
||||
for (HttpMessageWriter<?> converter : getMessageWriters()) {
|
||||
if (converter.canWrite(elementType, null)) {
|
||||
writableMediaTypes.addAll(converter.getWritableMediaTypes());
|
||||
writableMediaTypes.addAll(converter.getWritableMediaTypes(elementType));
|
||||
}
|
||||
}
|
||||
return writableMediaTypes;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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,6 +28,8 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import io.reactivex.rxjava3.core.Completable;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -78,6 +80,9 @@ import static org.springframework.web.testfixture.method.ResolvableMethod.on;
|
|||
*/
|
||||
public class ResponseEntityResultHandlerTests {
|
||||
|
||||
private static final String NEWLINE_SYSTEM_PROPERTY = System.getProperty("line.separator");
|
||||
|
||||
|
||||
private ResponseEntityResultHandler resultHandler;
|
||||
|
||||
|
||||
|
|
@ -393,6 +398,37 @@ public class ResponseEntityResultHandlerTests {
|
|||
.verify();
|
||||
}
|
||||
|
||||
@Test // gh-26212
|
||||
public void handleWithObjectMapperByTypeRegistration() throws Exception {
|
||||
MediaType halFormsMediaType = MediaType.parseMediaType("application/prs.hal-forms+json");
|
||||
MediaType halMediaType = MediaType.parseMediaType("application/hal+json");
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
|
||||
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
|
||||
encoder.registerObjectMappersForType(Person.class, map -> map.put(halMediaType, objectMapper));
|
||||
EncoderHttpMessageWriter<?> writer = new EncoderHttpMessageWriter<>(encoder);
|
||||
|
||||
ResponseEntityResultHandler handler = new ResponseEntityResultHandler(
|
||||
Collections.singletonList(writer), new RequestedContentTypeResolverBuilder().build());
|
||||
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(
|
||||
get("/path").header("Accept", halFormsMediaType + "," + halMediaType));
|
||||
|
||||
ResponseEntity<Person> value = ResponseEntity.ok().body(new Person("Jason"));
|
||||
MethodParameter returnType = on(TestController.class).resolveReturnType(entity(Person.class));
|
||||
HandlerResult result = handlerResult(value, returnType);
|
||||
|
||||
handler.handleResult(exchange, result).block();
|
||||
|
||||
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(halMediaType);
|
||||
assertThat(exchange.getResponse().getBodyAsString().block()).isEqualTo(
|
||||
"{" + NEWLINE_SYSTEM_PROPERTY +
|
||||
" \"name\" : \"Jason\"" + NEWLINE_SYSTEM_PROPERTY +
|
||||
"}");
|
||||
}
|
||||
|
||||
|
||||
private void testHandle(Object returnValue, MethodParameter returnType) {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(get("/path"));
|
||||
|
|
@ -451,6 +487,8 @@ public class ResponseEntityResultHandlerTests {
|
|||
|
||||
ResponseEntity<Void> responseEntityVoid() { return null; }
|
||||
|
||||
ResponseEntity<Person> responseEntityPerson() { return null; }
|
||||
|
||||
HttpHeaders httpHeaders() { return null; }
|
||||
|
||||
Mono<ResponseEntity<String>> mono() { return null; }
|
||||
|
|
@ -470,4 +508,26 @@ public class ResponseEntityResultHandlerTests {
|
|||
Object object() { return null; }
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class Person {
|
||||
|
||||
private String name;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue