在 Spring Boot 应用程序中配置 Jackson mixin



我为我的班级创建了一个mixin。mixin本身工作正常,这不是大多数人混合faterxml/codehaus注释的问题。 我在单元测试中对其进行了测试,在使用addMixIn方法时"手动"创建了ObjectMapper - 它工作得很好。

我想使用该 mixin 来修改从我的 REST 端点返回的响应 json。 我尝试以许多不同的方式自定义Spring Boot的ObjectMapper:

生成器定制器:

@Bean
public Jackson2ObjectMapperBuilderCustomizer addMixin(){
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.mixIn(MyClass.class, MyClassMixin.class);                
}
};
}

建筑工人:

@Bean
Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder().mixIn(MyClass.class, MyClassMixin.class);
}

转炉:

@Bean
public MappingJackson2HttpMessageConverter configureJackson(){
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(MyClass.class, MyClassMixin.class);
converter.setObjectMapper(mapper);
return converter;
}

对象映射器:

@Autowired(required = true)
public void configureJackon(ObjectMapper jsonMapper){
jsonMapper.addMixIn(MyClass.class, MyClassMixin.class);
}

这些都不起作用。

从 Spring Boot 2.7 开始,内置了对 mixins 的支持。

添加以下注释:

@JsonMixin(MyClass::class)
class MyClassMixin{

将在自动配置的ObjectMapper中注册 mixin。

这可能取决于 Spring Boot 版本,但根据自定义 Jackson ObjectMapper 定义一个新的Jackson2ObjectMapperBuilderCustomizerBean 就足够

了 上下文的 Jackson2ObjectMapperBuilder

可以由一个或多个 Jackson2ObjectMapperBuilderCustomizer bean 自定义。可以订购此类定制器 bean(Boot 自己的定制器的顺序为 0(,允许在 Boot 自定义之前和之后应用其他自定义。

我已经尝试了上述方法,但它对我也不起作用。在调试时,我注意到消息转换器中的 ObjectMapper 为空。

参考帖子获取注册的消息转换器,我最终替换了 Jackson 的默认消息转换器,允许我根据需要自定义对象映射器:

@SpringBootApplication
@RestController
public class MixinTest {
public static void main(String[] args) {
SpringApplication.run(MixinTest.class, args);
}
static class Person {
private String title;
private String name;
private String nullField;
private LocalDate date;
Person(String title, String name) {
this.title = title;
this.name = name;
this.date = LocalDate.now();
}
// getters here...
}
// this will exclude nullField 
@JsonInclude(JsonInclude.Include.NON_NULL)
interface PersonMixin {
@JsonProperty("fullName")
String getName();
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer personCustomizer() {
return jacksonObjectMapperBuilder ->
jacksonObjectMapperBuilder.mixIn(Person.class, PersonMixin.class);
}
@Bean
public MappingJackson2HttpMessageConverter myMessageConverter(
// provided by Spring
RequestMappingHandlerAdapter reqAdapter,
Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
ObjectMapper mapper = jacksonObjectMapperBuilder
.featuresToEnable(SerializationFeature.INDENT_OUTPUT)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.modulesToInstall(new JavaTimeModule())
.build();
// **replace previous MappingJackson converter**
List<HttpMessageConverter<?>> converters = 
reqAdapter.getMessageConverters();
converters.removeIf(httpMessageConverter ->
httpMessageConverter.getClass()
.equals(MappingJackson2HttpMessageConverter.class));
MappingJackson2HttpMessageConverter jackson = new 
MappingJackson2HttpMessageConverter(mapper);
converters.add(jackson);
reqAdapter.setMessageConverters(converters);
return jackson;
}
@GetMapping("/test")
public Person get() {
return new Person("Mr", "Joe Bloggs");
}
}

点击 http://localhost:8080/test 后在浏览器中输出以下内容:

{
"title" : "Mr",
"date" : "2019-09-03",
"fullName" : "Joe Bloggs"
}

这样,我应该能够根据需要添加任意数量的定制器。我相信有更好的方法可以做到这一点。像这样替换内部似乎很笨拙......

最新更新