diff --git a/spring-cloud-function-web/pom.xml b/spring-cloud-function-web/pom.xml
index 0c078cfb4..2b07ef926 100644
--- a/spring-cloud-function-web/pom.xml
+++ b/spring-cloud-function-web/pom.xml
@@ -23,6 +23,11 @@
com.google.code.gson
gson
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ true
+
org.springframework.cloud
spring-cloud-function-context
diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java
index af002ba84..814c27806 100644
--- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java
+++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/ReactorAutoConfiguration.java
@@ -19,22 +19,32 @@ package org.springframework.cloud.function.web.flux;
import java.util.ArrayList;
import java.util.List;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.cloud.function.context.FunctionCatalog;
import org.springframework.cloud.function.context.catalog.FunctionInspector;
import org.springframework.cloud.function.web.flux.request.FluxHandlerMethodArgumentResolver;
import org.springframework.cloud.function.web.flux.response.FluxReturnValueHandler;
+import org.springframework.cloud.function.web.util.GsonMapper;
+import org.springframework.cloud.function.web.util.JacksonMapper;
+import org.springframework.cloud.function.web.util.JsonMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.convert.ConversionService;
@@ -55,11 +65,14 @@ import reactor.core.publisher.Flux;
@ConditionalOnWebApplication
@ConditionalOnClass({ Flux.class, AsyncHandlerMethodReturnValueHandler.class })
@Import(FunctionController.class)
+@AutoConfigureAfter({ JacksonAutoConfiguration.class, GsonAutoConfiguration.class })
public class ReactorAutoConfiguration {
@Autowired
private ApplicationContext context;
+ static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
+
@Bean
public FunctionHandlerMapping functionHandlerMapping(FunctionCatalog catalog,
FunctionController controller) {
@@ -87,7 +100,7 @@ public class ReactorAutoConfiguration {
protected static class FluxArgumentResolverConfiguration {
@Bean
public FluxHandlerMethodArgumentResolver fluxHandlerMethodArgumentResolver(
- FunctionInspector inspector, Gson mapper) {
+ FunctionInspector inspector, JsonMapper mapper) {
return new FluxHandlerMethodArgumentResolver(inspector, mapper);
}
}
@@ -116,6 +129,44 @@ public class ReactorAutoConfiguration {
};
}
+ @Configuration
+ @ConditionalOnClass(Gson.class)
+ @Conditional(PreferGsonOrMissingJacksonCondition.class)
+ protected static class GsonConfiguration {
+ @Bean
+ public GsonMapper jsonMapper(Gson gson) {
+ return new GsonMapper(gson);
+ }
+ }
+
+ @Configuration
+ @ConditionalOnClass(ObjectMapper.class)
+ @ConditionalOnProperty(name = ReactorAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jackson", matchIfMissing = true)
+ protected static class JacksonConfiguration {
+ @Bean
+ public JacksonMapper jsonMapper(ObjectMapper mapper) {
+ return new JacksonMapper(mapper);
+ }
+ }
+
+ private static class PreferGsonOrMissingJacksonCondition extends AnyNestedCondition {
+
+ PreferGsonOrMissingJacksonCondition() {
+ super(ConfigurationPhase.REGISTER_BEAN);
+ }
+
+ @ConditionalOnProperty(name = ReactorAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
+ static class GsonPreferred {
+
+ }
+
+ @ConditionalOnMissingBean(ObjectMapper.class)
+ static class JacksonMissing {
+
+ }
+
+ }
+
private static class BasicStringConverter implements StringConverter {
private ConversionService conversionService;
diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java
index b7c7e1e7c..7a90fb165 100644
--- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java
+++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java
@@ -16,7 +16,6 @@
package org.springframework.cloud.function.web.flux.request;
-import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
@@ -24,9 +23,6 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
-import com.google.gson.Gson;
-import com.google.gson.JsonSyntaxException;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -34,13 +30,14 @@ import org.springframework.cloud.function.context.catalog.FunctionInspector;
import org.springframework.cloud.function.context.message.MessageUtils;
import org.springframework.cloud.function.web.flux.constants.WebRequestConstants;
import org.springframework.cloud.function.web.util.HeaderUtils;
+import org.springframework.cloud.function.web.util.JsonMapper;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
-import org.springframework.core.ResolvableType;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.StreamUtils;
+import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
@@ -59,11 +56,12 @@ public class FluxHandlerMethodArgumentResolver
private static Log logger = LogFactory
.getLog(FluxHandlerMethodArgumentResolver.class);
- private final Gson mapper;
+ private final JsonMapper mapper;
private FunctionInspector inspector;
- public FluxHandlerMethodArgumentResolver(FunctionInspector inspector, Gson mapper) {
+ public FluxHandlerMethodArgumentResolver(FunctionInspector inspector,
+ JsonMapper mapper) {
this.inspector = inspector;
this.mapper = mapper;
}
@@ -84,7 +82,7 @@ public class FluxHandlerMethodArgumentResolver
type = Object.class;
}
boolean message = inspector.isMessage(handler);
- List