如何自定义Spring Boot隐式使用的Jackson JSON映射器?

时间:2015-02-04 14:54:20

标签: java spring spring-mvc jackson spring-boot

我正在使用Spring Boot(1.2.1),其方式与Building a RESTful Web Service教程类似:

@RestController
public class EventController {

    @RequestMapping("/events/all")
    EventList events() {
        return proxyService.getAllEvents();
    }

}

如上所述,Spring MVC隐式使用Jackson将我的EventList对象序列化为JSON。

但我想对JSON格式进行一些简单的自定义,例如:

setSerializationInclusion(JsonInclude.Include.NON_NULL)

问题是,自定义隐式JSON映射器的最简单方法是什么?

我在 this blog post 中尝试了这种方法,创建了一个CustomObjectMapper等等,但是第3步“在Spring上下文中注册类”失败了:

org.springframework.beans.factory.BeanCreationException: 
  Error creating bean with name 'jacksonFix': Injection of autowired dependencies failed; 
  nested exception is org.springframework.beans.factory.BeanCreationException: 
  Could not autowire method: public void com.acme.project.JacksonFix.setAnnotationMethodHandlerAdapter(org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter); 
  nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
  No qualifying bean of type [org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter]   
  found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

看起来这些指令适用于旧版本的Spring MVC,而我正在寻找一种简单的方法来使用最新的Spring Boot。

11 个答案:

答案 0 :(得分:94)

如果您使用的是Spring Boot 1.3,则可以通过application.properties配置序列化包含:

spring.jackson.serialization-inclusion=non_null

在Jackson 2.7中进行更改后,Spring Boot 1.4使用了名为spring.jackson.default-property-inclusion的属性:

spring.jackson.default-property-inclusion=non_null

请参阅Spring Boot文档中的“Customize the Jackson ObjectMapper”部分。

如果您使用的是早期版本的Spring Boot,那么在Spring Boot中配置序列化包含的最简单方法是声明您自己的,适当配置的Jackson2ObjectMapperBuilder bean。例如:

@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.serializationInclusion(JsonInclude.Include.NON_NULL);
    return builder;
}

答案 1 :(得分:20)

很多东西都可以在applicationproperties中配置。不幸的是,此功能仅在版本1.3中,但您可以添加到Config-Class

@Autowired(required = true)
public void configureJackson(ObjectMapper jackson2ObjectMapper) {
    jackson2ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}

[更新:您必须处理ObjectMapper,因为在运行配置之前调用了build() - 方法。]

答案 2 :(得分:19)

我对这个问题的回答有点迟了,但将来有人可能会发现这个问题很有用。除了许多其他方法之外,下面的方法效果最好,我个人认为更适合Web应用程序。

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {

 ... other configurations

@Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        builder.propertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
        builder.serializationInclusion(Include.NON_EMPTY);
        builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
    }
}

答案 3 :(得分:17)

The documentation说明了几种方法。

  

如果您想完全替换默认ObjectMapper,请定义该类型的@Bean并将其标记为@Primary

     

定义@Bean类型Jackson2ObjectMapperBuilder,您可以自定义默认ObjectMapperXmlMapper(分别用于MappingJackson2HttpMessageConverterMappingJackson2XmlHttpMessageConverter )。

答案 4 :(得分:9)

spring.jackson.serialization-inclusion=non_null曾经为我们工作

但是当我们将spring boot版本升级到1.4.2.RELEASE或更高版本时,它就停止了工作。

现在,另一个属性spring.jackson.default-property-inclusion=non_null正在发挥魔力。

实际上,serialization-inclusion已被弃用。这就是我的intellij对我的看法。

  

不推荐使用:不推荐使用ObjectMapper.setSerializationInclusion   杰克逊2.7

因此,请先使用spring.jackson.default-property-inclusion=non_null

答案 5 :(得分:5)

您可以在引导类中添加以下方法,该方法以@SpringBootApplication注释

    @Bean
    @Primary
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);

    objectMapper.registerModule(new JodaModule());

    return objectMapper;
}

答案 6 :(得分:3)

我偶然发现了另一个解决方案,这非常好。

基本上,只做step 2 from the blog posted mentioned,并将自定义ObjectMapper定义为Spring @Component。 (当我从步骤3中移除所有AnnotationMethodHandlerAdapter时,事情就开始起作用了。)

@Component
@Primary
public class CustomObjectMapper extends ObjectMapper {
    public CustomObjectMapper() {
        setSerializationInclusion(JsonInclude.Include.NON_NULL); 
        configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
    }
}

只要组件位于Spring扫描的包中,就可以正常工作。 (在我的情况下,使用@Primary并不是强制性的,但为什么不明确说明。)

对我来说,与其他方法相比有两个好处:

  • 这更简单;我可以从Jackson扩展一个类,而不需要知道像Jackson2ObjectMapperBuilder这样的高度特定于Spring的内容。
  • 我想使用相同的Jackson配置在我的应用程序的另一部分反序列化JSON,这样很简单:new CustomObjectMapper()而不是new ObjectMapper()

答案 7 :(得分:0)

我找到了上述解决方案:

<强> spring.jackson.serialization系夹杂物= non_null

仅从1.4.0.RELEASE版本的spring boot开始工作。在所有其他情况下,配置将被忽略。

我通过尝试修改弹簧靴样品“spring-boot-sample-jersey”来验证这一点

答案 8 :(得分:0)

我知道要求Spring启动的问题,但我相信很多人都在寻找如何在非Spring启动时执行此操作,就像我几乎整天搜索一样。

在Spring 4之上,如果您只打算配置MappingJacksonHttpMessageConverter,则无需配置ObjectMapper

你只需要这样做:

public class MyObjectMapper extends ObjectMapper {

    private static final long serialVersionUID = 4219938065516862637L;

    public MyObjectMapper() {
        super();
        enable(SerializationFeature.INDENT_OUTPUT);
    }       
}

在Spring配置中,创建此bean:

@Bean 
public MyObjectMapper myObjectMapper() {        
    return new MyObjectMapper();
}

答案 9 :(得分:0)

当我尝试在Spring Boot 2.0.6中使ObjectMapper成为主要对象时,出现错误 因此,我修改了弹簧靴为我创建的那个

另请参见https://stackoverflow.com/a/48519868/255139

@Lazy
@Autowired
ObjectMapper mapper;

@PostConstruct
public ObjectMapper configureMapper() {
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

    mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, true);
    mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

    SimpleModule module = new SimpleModule();
    module.addDeserializer(LocalDate.class, new LocalDateDeserializer());
    module.addSerializer(LocalDate.class, new LocalDateSerializer());
    mapper.registerModule(module);

    return mapper;
}

答案 10 :(得分:0)

向Spring Boot预先配置的ObjectMapper添加更多配置的正确方法是定义Jackson2ObjectMapperBuilderCustomizer。否则,您将覆盖不想删除的Springs配置。

 @Configuration
public class MyJacksonConfigurer implements Jackson2ObjectMapperBuilderCustomizer {
    @Override
    public void customize(Jackson2ObjectMapperBuilder builder) {
        builder.deserializerByType(LocalDate.class, new MyOwnJsonLocalDateTimeDeserializer());
    }
}