【问题标题】:Force SpingBoot to use Gson over Jackson强制 Spring Boot 使用 Gson 或 Jackson
【发布时间】:2020-09-24 16:19:59
【问题描述】:

我试图强制 SpringBoot 使用 Gson 而不是 Jackson。我已经阅读了我在网上找到的大部分文章,但我仍然看到杰克逊被使用。这就是我所做的

  1. 已添加
spring:
  http: { converters: { preferred-json-mapper: gson } }
  mvc: { converters: {preferred-json-mapper: gson } }

在 application.yaml 中

  1. 更新了 POM
    • 添加了gson 依赖
    • jackson-databind 添加到spring-boot-starter-web 依赖项的排除列表中。
  2. 在主类中添加了@EnableAutoConfiguration(exclude = JacksonAutoConfiguration.class)
  3. 写在@Configuration类下面:
@Configuration
@Slf4j
public class MyConfig implements WebMvcConfigurer {
  
  @Override
  public void extendMessageConverters (List<HttpMessageConverters<?>> converters) {
    log.debug("Setting gson converter");
    converters.add(new GsonHttpMessageConverter(myCustomGsonInstance()));
  }

  public Gson myCustomGsonInstance() {
    return new Gson();
  }
}

在调试中运行测试时,我可以看到 Jackson 仍然列在 HttpMessageConverters 列表中,而 Gson 没有。


更新: 在实时运行和以下测试类中会看到此行为。

@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = MOCK)
@ExtendWith(MockitoExtension.class)
public class MyTestClass {

  @Autowired
  private MyController controller;
  
  private MockMvc mockMvc;

  @BeforeEach
  public void setUp(){
    mockMvc = MockMvcBuilders.standaloneSetup(controller)
    // .setMessageConverters(new GsonHttpMessageConverter(myCustomGsonInstance())) // if I add this, the test passes.
    .build();
  }
  
  @Test
  public void happyFlow(){
    // given
    URI uri = "/test/uri";
    HttpHeaders headers = new HttpHeaders();
    headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
    
    // when
    String responseBody = mockMvc.perform(get(uri).headers(headers)).andReturn().getResponse().getContentAsString();

    // then
    assertThat(responseBody, wasSerializedByGson());
  }
}

【问题讨论】:

  • 当你不是从测试运行时(我的意思是在调试模式下启动应用程序,你会看到什么)?还请显示测试的骨架,根据注释的不同,它的行为可能会有所不同?
  • 你的myCustomGsonInstance()来自哪里?这已经是 ApplicationContext 中的 bean 了吗?
  • 只是同一个类中的一个方法,它返回一个 Gson 的实例。为清晰起见进行了更新。
  • 为什么要手动配置MockMvc 你应该在MockMvc 上使用@Autowired

标签: spring-boot gson


【解决方案1】:

您似乎在配置首选 JSON 映射器时使用了错误的属性。您正在使用spring.http.converters.preferred-json-mapper,但正确的属性是spring.mvc.converters.preferred-json-mapper。在application.yaml 中,将是以下内容:

spring:
  mvc:
    converters:
      preferred-json-mapper: gson

【讨论】:

  • 仍在使用杰克逊
  • 谢谢@andy-wilkinson。我花了几个小时在这上面。所有文章都告诉我使用spring.http.converters.preferred-json-mapper,但对我不起作用。有了这个,我什至不必将 Gson 转换器添加到消息转换器列表中。自 SpringBoot 2.3 起,spring.http. properties 已移至server.servlet.encoding.spring.mvc.spring.codec.
【解决方案2】:

Spring Boot 自带 Gson 自动配置支持:Source Code

因此,除了启用 yaml 属性之外,您还必须自动装配 Gson 单例实例以供您的 WebMvcConfigurer 使用:

@Configuration
@Slf4j
public class MyConfig implements WebMvcConfigurer {

  @Autowired
  private Gson gson;
  
  @Override
  public void extendMessageConverters (List<HttpMessageConverters<?>> converters) {
    log.debug("Setting gson converter");
    converters.add(new GsonHttpMessageConverter(gson));
  }

}

还有从Andy Wilkinson借来的yaml属性:

spring:
  mvc:
    converters:
      preferred-json-mapper: gson

通过此设置,Spring MVC 使用与配置中的 Autowired 相同的 Gson 实例。

在你的测试中,它应该是这样的:

@WebMvcTest(MyController.class)
public class MyTestClass {

  @Autowired
  private MockMvc mockMvc;
  @Autowired
  private MyController controller;

  @Test
  public void happyFlow(){
    // given
    URI uri = "/test/uri";
    HttpHeaders headers = new HttpHeaders();
    headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
    
    // when
    String responseBody = mockMvc.perform(get(uri).headers(headers)).andReturn().getResponse().getContentAsString();

    // then
    assertThat(responseBody, wasSerializedByGson());
  }
}

【讨论】:

    猜你喜欢
    • 2017-04-08
    • 2022-01-04
    • 2017-09-30
    • 2017-06-28
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 2021-06-24
    相关资源
    最近更新 更多