Java 如何自定义 Spring Boot 隐式使用的 Jackson JSON 映射器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28324352/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to customise the Hymanson JSON mapper implicitly used by Spring Boot?
提问by Jonik
I'm using Spring Boot (1.2.1), in a similar fashion as in their Building a RESTful Web Servicetutorial:
我正在使用 Spring Boot (1.2.1),其方式与他们在构建 RESTful Web 服务教程中的方式类似:
@RestController
public class EventController {
@RequestMapping("/events/all")
EventList events() {
return proxyService.getAllEvents();
}
}
So above, Spring MVC implicitly uses Hymanson for serialising my EventList
object into JSON.
所以在上面,Spring MVC 隐式地使用 Hymanson 将我的EventList
对象序列化为 JSON。
But I want to do some simple customisations to the JSON format, such as:
但我想对 JSON 格式进行一些简单的自定义,例如:
setSerializationInclusion(JsonInclude.Include.NON_NULL)
Question is, what is the simplest way to customise the implicit JSON mapper?
问题是,自定义隐式 JSON 映射器的最简单方法是什么?
I tried the approach in this blog post, creating a CustomObjectMapper and so on, but the step 3, "Register classes in the Spring context", fails:
我尝试了这篇博客文章中的方法,创建了一个 CustomObjectMapper 等等,但是第 3 步“在 Spring 上下文中注册类”失败了:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'HymansonFix': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire method: public void com.acme.project.HymansonFix.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: {}
It looks like those instructions are for older versions of Spring MVC, while I'm looking for a simple way to get this working with latest Spring Boot.
看起来这些说明适用于旧版本的 Spring MVC,而我正在寻找一种简单的方法来使其与最新的 Spring Boot 一起使用。
采纳答案by Andy Wilkinson
If you're using Spring Boot 1.3, you can configure serialisation inclusion via application.properties
:
如果您使用的是 Spring Boot 1.3,则可以通过application.properties
以下方式配置序列化包含:
spring.Hymanson.serialization-inclusion=non_null
Following changes in Hymanson 2.7, Spring Boot 1.4 uses a property named spring.Hymanson.default-property-inclusion
instead:
随着 Hymanson 2.7 的变化,Spring Boot 1.4 使用了一个名为的属性spring.Hymanson.default-property-inclusion
:
spring.Hymanson.default-property-inclusion=non_null
See "Customize the Hymanson ObjectMapper" section in Spring Boot documentation.
请参阅Spring Boot 文档中的“自定义 Hymanson ObjectMapper”部分。
If you're using an earlier version of Spring Boot, the easiest way to configure serialisation inclusion in Spring Boot is to declare your own, appropriately configured Hymanson2ObjectMapperBuilder
bean. For example:
如果您使用的是较早版本的 Spring Boot,在 Spring Boot 中配置序列化包含的最简单方法是声明您自己的、适当配置的Hymanson2ObjectMapperBuilder
bean。例如:
@Bean
public Hymanson2ObjectMapperBuilder objectMapperBuilder() {
Hymanson2ObjectMapperBuilder builder = new Hymanson2ObjectMapperBuilder();
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
return builder;
}
回答by Predrag Maric
The documentationstates several ways to do this.
文档说明了执行此操作的几种方法。
If you want to replace the default
ObjectMapper
completely, define a@Bean
of that type and mark it as@Primary
.Defining a
@Bean
of typeHymanson2ObjectMapperBuilder
will allow you to customize both defaultObjectMapper
andXmlMapper
(used inMappingHymanson2HttpMessageConverter
andMappingHymanson2XmlHttpMessageConverter
respectively).
如果要
ObjectMapper
完全替换默认值,请定义@Bean
该类型的 a 并将其标记为@Primary
。定义
@Bean
类型Hymanson2ObjectMapperBuilder
将允许您自定义默认ObjectMapper
和XmlMapper
(分别用于MappingHymanson2HttpMessageConverter
和MappingHymanson2XmlHttpMessageConverter
)。
回答by Jonik
I stumbled upon another solution, which is quite nice.
我偶然发现了另一个解决方案,它非常好。
Basically, only do step 2 from the blog posted mentioned, and define a custom ObjectMapper as a Spring @Component
. (Things started working when I just removedall the AnnotationMethodHandlerAdapter stuff from step 3.)
基本上,只执行提到的博客中的第 2 步,并将自定义 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);
}
}
Works as long as the component is in a package scanned by Spring. (Using @Primary
is not mandatory in my case, but why not make things explicit.)
只要组件在 Spring 扫描的包中就可以工作。(@Primary
在我的情况下使用不是强制性的,但为什么不明确说明。)
For me there are two benefits compared to the other approach:
对我来说,与其他方法相比有两个好处:
- This is simpler; I can just extend a class from Hymanson and don't need to know about highly Spring-specific stuff like
Hymanson2ObjectMapperBuilder
. - I want to use the same Hymanson configs for deserialising JSON in another part of my app, and this way it's very simple:
new CustomObjectMapper()
instead ofnew ObjectMapper()
.
- 这更简单;我可以只从 Hymanson 扩展一个类,不需要了解高度特定于 Spring 的东西,比如
Hymanson2ObjectMapperBuilder
. - 我想在我的应用程序的另一部分使用相同的 Hymanson 配置来反序列化 JSON,这样就非常简单:
new CustomObjectMapper()
而不是new ObjectMapper()
.
回答by Vijay Veeraraghavan
I am answering bit late to this question, but someone, in future, might find this useful. The below approach, besides lots of other approaches, works best, and I personally think would better suit a web application.
我对这个问题的回答有点晚,但将来有人可能会发现这很有用。除了许多其他方法之外,下面的方法效果最好,我个人认为更适合 Web 应用程序。
@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {
... other configurations
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Hymanson2ObjectMapperBuilder builder = new Hymanson2ObjectMapperBuilder();
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 MappingHymanson2HttpMessageConverter(builder.build()));
converters.add(new MappingHymanson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
}
}
回答by nbank
A lot of things can configured in applicationproperties. Unfortunately this feature only in Version 1.3, but you can add in a Config-Class
很多东西都可以在 applicationproperties 中配置。不幸的是,此功能仅在 1.3 版中出现,但您可以添加一个 Config-Class
@Autowired(required = true)
public void configureHymanson(ObjectMapper Hymanson2ObjectMapper) {
Hymanson2ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
[UPDATE: You must work on the ObjectMapper because the build()
-method is called before the config is runs.]
[更新:您必须在 ObjectMapper 上工作,因为在build()
运行配置之前调用了-method。]
回答by Tim Dugan
I found the solution described above with :
我找到了上述解决方案:
spring.Hymanson.serialization-inclusion=non_null
spring.Hymanson.serialization-inclusion=non_null
To only work starting at the 1.4.0.RELEASE version of spring boot. In all other cases the config is ignored.
仅从 spring boot 的 1.4.0.RELEASE 版本开始工作。在所有其他情况下,配置将被忽略。
I verified this by experimenting with a modification of the spring boot sample "spring-boot-sample-jersey"
我通过试验修改弹簧靴样本“spring-boot-sample-jersey”来验证这一点
回答by so-random-dude
spring.Hymanson.serialization-inclusion=non_null
used to work for us
spring.Hymanson.serialization-inclusion=non_null
曾经为我们工作
But when we upgraded spring boot version to 1.4.2.RELEASE or higher, it stopped working.
但是当我们将 spring boot 版本升级到 1.4.2.RELEASE 或更高版本时,它停止工作。
Now, another property spring.Hymanson.default-property-inclusion=non_null
is doing the magic.
现在,另一个属性spring.Hymanson.default-property-inclusion=non_null
正在发挥作用。
in fact, serialization-inclusion
is deprecated. This is what my intellij throws at me.
事实上,serialization-inclusion
已被弃用。这就是我的intellij 扔给我的东西。
Deprecated: ObjectMapper.setSerializationInclusion was deprecated in Hymanson 2.7
已弃用:ObjectMapper.setSerializationInclusion 在 Hymanson 2.7 中已弃用
So, start using spring.Hymanson.default-property-inclusion=non_null
instead
因此,开始使用spring.Hymanson.default-property-inclusion=non_null
替代
回答by GMsoF
I know the question asking for Spring boot, but I believe lot of people looking for how to do this in non Spring boot, like me searching almost whole day.
我知道要求 Spring Boot 的问题,但我相信很多人都在寻找如何在非 Spring Boot 中执行此操作,就像我几乎整天都在搜索一样。
Above Spring 4, there is no need to configure MappingHymansonHttpMessageConverter
if you only intend to configure ObjectMapper
.
Spring 4 以上,MappingHymansonHttpMessageConverter
如果只打算配置就不需要配置ObjectMapper
。
You just need to do:
你只需要做:
public class MyObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 4219938065516862637L;
public MyObjectMapper() {
super();
enable(SerializationFeature.INDENT_OUTPUT);
}
}
And in your Spring configuration, create this bean:
在你的 Spring 配置中,创建这个 bean:
@Bean
public MyObjectMapper myObjectMapper() {
return new MyObjectMapper();
}
回答by sendon1982
You can add a following method inside your bootstrap class which is annotated with @SpringBootApplication
您可以在引导类中添加以下方法,该方法带有注释 @SpringBootApplication
@Bean
@Primary
public ObjectMapper objectMapper(Hymanson2ObjectMapperBuilder 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;
}
回答by Kalpesh Soni
When I tried to make ObjectMapper primary in spring boot 2.0.6 I got errors So I modified the one that spring boot created for me
当我尝试在 spring boot 2.0.6 中使 ObjectMapper 成为主要对象时,我遇到了错误 所以我修改了 spring boot 为我创建的那个
Also see https://stackoverflow.com/a/48519868/255139
另见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;
}