【问题标题】:Force Spring-Boot to use Gson instead of Jackson强制 Spring-Boot 使用 Gson 而不是 Jackson
【发布时间】:2017-04-08 18:07:54
【问题描述】:

Spring-Boot 1.4.2 参考声明:

spring.http.converters.preferred-json-mapper=jackson # 用于 HTTP 消息转换的首选 JSON 映射器。设置为“gson”强制使用Gson

我们做到了。

  • 我们将 gson 设置为 preferred-json-mapper。
  • 我们已将 Gson 添加为项目的依赖项。

但仍然使用杰克逊。

最后,在排除了 Maven 中指向 Jackson 的所有传递依赖项后,我们设法强制 Spring-Boot 使用 Gson。

现在的问题是。这是强制 Spring-Boot 使用 Gson 而不是 Jackson 的唯一方法吗?我们真的需要排除所有指向杰克逊的传递依赖吗? preferred-json-mapper 设置不够?

【问题讨论】:

标签: spring-boot


【解决方案1】:

发生在 Spring Boot 使用的旧 *.xml 配置的一部分中,我们有 <mvc:annotation-driven/>

它导致第二次使用没有 GsonHttpMessageConverter 的默认转换器创建 RequestMappingHandlerAdapter。

【讨论】:

    【解决方案2】:

    好吧,WebMvcConfigurerAdapter弃用。从 Spring 5.0 开始,请执行以下操作:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Bean
        public Gson gson() {
            GsonBuilder b = new GsonBuilder();
            b.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY);
            b.registerTypeAdapterFactory(DateTypeAdapter.FACTORY);
            b.registerTypeAdapterFactory(TimestampTypeAdapter.FACTORY);
            b.registerTypeAdapterFactory(LocalDateTypeAdapter.FACTORY);
            b.registerTypeAdapterFactory(LocalDateTimeTypeAdapter.FACTORY);
            return b.create();
        }
    
        @Override
        public void configureMessageConverters(
            List<HttpMessageConverter<?>> converters) {
            StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
            stringConverter.setWriteAcceptCharset(false);
            stringConverter.setSupportedMediaTypes(Collections
                .singletonList(MediaType.TEXT_PLAIN));
            converters.add(stringConverter);
            converters.add(new ByteArrayHttpMessageConverter());
            converters.add(new SourceHttpMessageConverter<>());
            GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();
            gsonHttpMessageConverter.setGson(gson());
            gsonHttpMessageConverter.setSupportedMediaTypes(Arrays
                .asList(MediaType.APPLICATION_JSON));
            converters.add(gsonHttpMessageConverter);
        }
    }
    

    【讨论】:

    • 这行得通,谢谢。但为什么所有这些工厂?他们需要额外的依赖,但即使只是使用 DateTypeAdapter(包含在 Gson 中),这个解决方案似乎对我有用......
    • 很好,但我会选择extendMessageConvertersThis may be useful for example to allow default converters to be registered and then insert a custom converter through this method.
    【解决方案3】:

    F.e. 1) 添加其他 json 工件,如果使用 maven 和 google json 命名为 gson

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>${latestGsonVersion}</version>
    </dependency>
    

    2) 设置

    spring.http.converters.preferred-json-mapper=gson
    

    3) 例如在代码中使用它

    @Autowired private Gson gson;
    

    还有其他的: Jackson 库、Google-Gson 库、JSON-lib、Flexjson、json-io、genson、JSONiJ 库。

    【讨论】:

    • 不工作。我可以阅读此异常:com.fasterxml.jackson.databind.exc.MismatchedInputException,注意:此异常与本文无关。只是我看到了活跃的转换器库。
    【解决方案4】:

    查看 Spring 源码。您必须完全从依赖项中排除 Jackson。我找不到spring.http.converters.preferred-json-mapper 的使用位置。

    https://github.com/spring-projects/spring-boot/issues/7518

    public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConverter {
    
        private static final boolean jaxb2Present;
    
        private static final boolean jackson2Present;
    
        private static final boolean jackson2XmlPresent;
    
        private static final boolean jackson2SmilePresent;
    
        private static final boolean gsonPresent;
    
        private static final boolean jsonbPresent;
    
        static {
            ClassLoader classLoader = AllEncompassingFormHttpMessageConverter.class.getClassLoader();
            jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
            jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
                            ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
            jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
            jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
            gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
            jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
        }
    
    
        public AllEncompassingFormHttpMessageConverter() {
            try {
                addPartConverter(new SourceHttpMessageConverter<>());
            }
            catch (Error err) {
                // Ignore when no TransformerFactory implementation is available
            }
    
            if (jaxb2Present && !jackson2XmlPresent) {
                addPartConverter(new Jaxb2RootElementHttpMessageConverter());
            }
    
            // THIS IS HERE
            if (jackson2Present) {
                addPartConverter(new MappingJackson2HttpMessageConverter());
            }
            else if (gsonPresent) {
                addPartConverter(new GsonHttpMessageConverter());
            }
            else if (jsonbPresent) {
                addPartConverter(new JsonbHttpMessageConverter());
            }
    
            if (jackson2XmlPresent) {
                addPartConverter(new MappingJackson2XmlHttpMessageConverter());
            }
    
            if (jackson2SmilePresent) {
                addPartConverter(new MappingJackson2SmileHttpMessageConverter());
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-17
      • 1970-01-01
      • 2020-09-11
      • 2015-02-25
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      相关资源
      最近更新 更多