在Spring中配置ObjectMapper


91

我的目标是配置objectMapper方式,使其仅序列化带有注释的元素@JsonProperty

为了做到这一点,我按照以下说明进行了说明,该说明说明了如何配置对象映射器。

我包括自定义描述objectmapper这里

但是,当类NumbersOfNewEvents被序列化时,它仍包含json中的所有属性。

有人暗示吗?提前致谢

杰克逊1.8.0春季3.0.5

CustomObjectMapper

public class CompanyObjectMapper extends ObjectMapper {
    public CompanyObjectMapper() {
        super();
        setVisibilityChecker(getSerializationConfig()
                .getDefaultVisibilityChecker()
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
                .withFieldVisibility(JsonAutoDetect.Visibility.NONE)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.DEFAULT));
    }
}

servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="de.Company.backend.web" />

    <mvc:annotation-driven />

    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                    <property name="objectMapper" ref="jacksonObjectMapper" />
                </bean>
            </list>
        </property>
    </bean>

    <bean id="jacksonObjectMapper" class="de.Company.backend.web.CompanyObjectMapper" />
</beans>

NumbersOfNewEvents

public class NumbersOfNewEvents implements StatusAttribute {

    public Integer newAccepts;
    public Integer openRequests;

    public NumbersOfNewEvents() {
        super();
    }
}

Answers:


135

使用Spring Boot(1.2.4)和Jackson(2.4.6),以下基于注释的配置对我有用。

@Configuration
public class JacksonConfiguration {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);

        return mapper;
    }
}

3
Spring支持在application.properties中自定义Jackson的一些属性:docs.spring.io/spring-boot/docs/current/reference/html/…–
NangSaigon

10
大家好。我遇到一个问题,当您在java config中用名称objectMapper声明bean时(如示例所示),Spring Boot会忽略此bean,即使您将\ @放置在系统中,该名字的bean也已在系统中注册。主注释。要解决此问题,您需要注册具有不同名称的bean,例如jsonObjectMapper,并用\ @Primary批注对其进行标记
Demwis

如果您使用Spring Boot,请参考我的答案
睡鼠

一个问题:您必须为班级命名JacksonConfiguration吗?这是一种指示Spring Boot将此类用作Jackson的配置类的自动方法。
Marco Sulla

使用还真的有效@EnableWebMvc吗?我怀疑是因为...在我的答案中看到:为什么@EnableWebMvc使用是一个问题?
adrhc

25

可能是因为我使用的是Spring 3.1(而不是您指定的Spring 3.0.5),但是Steve Eastwood的答案对我不起作用。此解决方案适用于Spring 3.1:

在您的spring xml上下文中:

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="objectMapper" ref="jacksonObjectMapper" />
        </bean>        
    </mvc:message-converters>
</mvc:annotation-driven>

<bean id="jacksonObjectMapper" class="de.Company.backend.web.CompanyObjectMapper" />

这有助于利用杰克逊2.X与Spring 3.1:stackoverflow.com/questions/10420040/...
亚兰·科恰良

有用!从Spring 3.0升级到3.2时,必须采用这种方法来注册我的自定义ObjectMapper。先前在定义MappingJacksonJsonView bean时一直在设置objectMapper属性,但是不再起作用。这是杰克逊1.7版
David Easley,

20

有很org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean长一段时间了。从Spring Boot的1.2版本开始,org.springframework.http.converter.json.Jackson2ObjectMapperBuilder提供Java Config。

在String Boot中,配置可以很简单:

spring.jackson.deserialization.<feature_name>=true|false
spring.jackson.generator.<feature_name>=true|false
spring.jackson.mapper.<feature_name>=true|false
spring.jackson.parser.<feature_name>=true|false
spring.jackson.serialization.<feature_name>=true|false
spring.jackson.default-property-inclusion=always|non_null|non_absent|non_default|non_empty

classpath:application.properties或一些Java代码@Configuration类:

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
    return builder;
}

看到:


2
这适用于大多数使用情况,但是,如果您使用@EnableWebMvc批注(在Spring Boot 2.0.3中进行了测试),则会忽略Spring Boot的jackson配置。
约翰

1
尽管我没有进行测试,但是我确定@EnableWebMvc不能使用(尽管使用或不使用Spring Boot)。为什么?看到WebMvcConfigurationSupport(DelegatingWebMvcConfiguration扩展WebMvcConfigurationSupport) Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json()
adrhc

16

我已经在Jackson 2.x和Spring 3.1.2+中使用了它

servlet-context.xml:

请注意,根元素为<beans:beans>,因此您可能需要根据设置beansmvc其删除并添加到其中的某些元素中。

    <annotation-driven>
        <message-converters>
            <beans:bean
                class="org.springframework.http.converter.StringHttpMessageConverter" />
            <beans:bean
                class="org.springframework.http.converter.ResourceHttpMessageConverter" />
            <beans:bean
                class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <beans:property name="objectMapper" ref="jacksonObjectMapper" />
            </beans:bean>
        </message-converters>
    </annotation-driven>

    <beans:bean id="jacksonObjectMapper"
        class="au.edu.unimelb.atcom.transfer.json.mappers.JSONMapper" />

au.edu.unimelb.atcom.transfer.json.mappers.JSONMapper.java:

public class JSONMapper extends ObjectMapper {

    public JSONMapper() {
        SimpleModule module = new SimpleModule("JSONModule", new Version(2, 0, 0, null, null, null));
        module.addSerializer(Date.class, new DateSerializer());
        module.addDeserializer(Date.class, new DateDeserializer());
        // Add more here ...
        registerModule(module);
    }

}

DateSerializer.java:

public class DateSerializer extends StdSerializer<Date> {

    public DateSerializer() {
        super(Date.class);
    }

    @Override
    public void serialize(Date date, JsonGenerator json,
            SerializerProvider provider) throws IOException,
            JsonGenerationException {
        // The client side will handle presentation, we just want it accurate
        DateFormat df = StdDateFormat.getBlueprintISO8601Format();
        String out = df.format(date);
        json.writeString(out);
    }

}

DateDeserializer.java:

public class DateDeserializer extends StdDeserializer<Date> {

    public DateDeserializer() {
        super(Date.class);
    }

    @Override
    public Date deserialize(JsonParser json, DeserializationContext context)
            throws IOException, JsonProcessingException {
        try {
            DateFormat df = StdDateFormat.getBlueprintISO8601Format();
            return df.parse(json.getText());
        } catch (ParseException e) {
            return null;
        }
    }

}

10

我现在基于https://github.com/FasterXML/jackson-module-hibernate找到了解决方案

我扩展了对象映射器,并在继承的构造函数中添加了属性。

然后,将新的对象映射器注册为bean。

<!-- https://github.com/FasterXML/jackson-module-hibernate -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <array>
            <bean id="jsonConverter"
            class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper">
                    <bean class="de.company.backend.spring.PtxObjectMapper"/>
                </property>
            </bean>
        </array>
    </property>
</bean>   

非常感谢您的解决方案!我花了四个多小时来研究<annotation-driven>,它只是没有使用转换器。尝试了您的答案,终于成功了!
snowindy 2013年

1
要使用注释,您只需注释自定义ObjectMapper@Component和扩展的Mapper @Primary。这是《 Spring参考指南》中推荐的方法,对我来说效果很好。
OlgaMaciaszek,2015年

9

如果要添加用于注册自定义序列化程序的自定义ObjectMapper,请尝试我的答案。

就我而言(春季3.2.4和杰克逊2.3.1),用于自定义序列化程序的XML配置:

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="false">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="serializers">
                        <array>
                            <bean class="com.example.business.serializer.json.CustomObjectSerializer"/>
                        </array>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

被无法解释的方式改写回默认值。

这为我工作:

CustomObject.java

@JsonSerialize(using = CustomObjectSerializer.class)
public class CustomObject {

    private Long value;

    public Long getValue() {
        return value;
    }

    public void setValue(Long value) {
        this.value = value;
    }
}

CustomObjectSerializer.java

public class CustomObjectSerializer extends JsonSerializer<CustomObject> {

    @Override
    public void serialize(CustomObject value, JsonGenerator jgen,
        SerializerProvider provider) throws IOException,JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeNumberField("y", value.getValue());
        jgen.writeEndObject();
    }

    @Override
    public Class<CustomObject> handledType() {
        return CustomObject.class;
    }
}

<mvc:message-converters>(...)</mvc:message-converters>解决方案中不需要XML配置()。


6

我正在使用Spring 4.1.6和Jackson FasterXML 2.1.4。

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <!-- 设置不输出null字段-->
                        <property name="serializationInclusion" value="NON_NULL"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

这适用于我的applicationContext.xml配置


6

解决方案1

第一个有效的解决方案(经过测试)非常有用,尤其是在使用@EnableWebMvc时:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private ObjectMapper objectMapper;// created elsewhere
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // this won't add a 2nd MappingJackson2HttpMessageConverter 
        // as the SOLUTION 2 is doing but also might seem complicated
        converters.stream().filter(c -> c instanceof MappingJackson2HttpMessageConverter).forEach(c -> {
            // check default included objectMapper._registeredModuleTypes,
            // e.g. Jdk8Module, JavaTimeModule when creating the ObjectMapper
            // without Jackson2ObjectMapperBuilder
            ((MappingJackson2HttpMessageConverter) c).setObjectMapper(this.objectMapper);
        });
    }

解决方案2

当然,下面的常用方法也可以使用(也可以使用@EnableWebMvc):

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private ObjectMapper objectMapper;// created elsewhere
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // this will add a 2nd MappingJackson2HttpMessageConverter 
        // (additional to the default one) but will work and you 
        // won't lose the default converters as you'll do when overwriting
        // configureMessageConverters(List<HttpMessageConverter<?>> converters)
        // 
        // you still have to check default included
        // objectMapper._registeredModuleTypes, e.g.
        // Jdk8Module, JavaTimeModule when creating the ObjectMapper
        // without Jackson2ObjectMapperBuilder
        converters.add(new MappingJackson2HttpMessageConverter(this.objectMapper));
    }

为什么@EnableWebMvc使用有问题?

@EnableWebMvc正在使用DelegatingWebMvcConfiguration哪个扩展WebMvcConfigurationSupport来做到这一点:

if (jackson2Present) {
    Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
    if (this.applicationContext != null) {
        builder.applicationContext(this.applicationContext);
    }
    messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}

这意味着无法使用@EnableWebMvc注入自己的文件ObjectMapper,以准备将其用于创建默认MappingJackson2HttpMessageConverter文件。


大!实际上,spring-data-rest-webmvc:3.2.3的一部分RepositoryRestMvcConfiguration并不使用Spring创建的ObjectMapper,只有带有模块的自定义objectMapper不能开箱即用。第一种方法是实际的,并替换由spring-data-rest-webmvc定制的ObjectMapper。谢谢!
Valtoni Boaventura

我遇到了一个问题,即我无法自定义EnableWebMvc的糟糕的ObjectMapper。很高兴我偶然发现了这一点。
埃文·怀特

3

在Spring Boot中,2.2.x您需要像这样配置它:

@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    return builder.build()
}

科特林:

@Bean
fun objectMapper(builder: Jackson2ObjectMapperBuilder) = builder.build()

2

在Spring 4之上,MappingJacksonHttpMessageConverter如果仅打算进行配置,则无需进行配置ObjectMapper

(配置MappingJacksonHttpMessageConverter将导致您丢失其他MessageConverter)

您只需要做:

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();
}

不工作- - customObjectMapper:通过方法在类路径资源定义的'customObjectMapper'[COM / Config.class] -_halObjectMapper: defined in null
Angshuman瓦尔

1
这仅适用于Spring Boot。不是普通的Spring Web。
睡鼠

2

要在普通spring-web中配置消息转换器,在这种情况下要启用Java 8 JSR-310 JavaTimeModule,您首先需要WebMvcConfigurer在您的@Configuration类中实现,然后重写该configureMessageConverters方法:

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().modules(new JavaTimeModule(), new Jdk8Module()).build()
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    converters.add(new MappingJackson2HttpMessageConverter(objectMapper));
}

这样,您可以注册ObjectMapper在基于Java的Spring配置中定义的任何自定义。


我希望通过Spring Boot注入和配置ObjectMapper。
君士坦丁堡Cronemberger '19

1
当然,如果您使用Spring Boot。这不是Spring Boot的问题。
睡鼠

是的,有趣的是,将Spring Web与Spring Boot一起使用时,它没有使用Spring Boot提供的ObjectMapper,这就是为什么我最后回答这个问题对我有所帮助。
君士坦丁堡Cronemberger '19

这将清除所有默认消息转换器!我很确定没有人想要这个。见我的答案的解决方案。
adrhc

好吧,如果你想扩展消息转换器,正确的解决方案是extendMessageConverters根据Spring文档重写。但是我不需要它,因为我只需要定制的MappingJackson2HttpMessageConverter
睡鼠

1

我正在使用Spring 3.2.4和Jackson FasterXML 2.1.1。

我创建了一个自定义的JacksonObjectMapper,它为映射的Objects的每个属性使用显式注释:

package com.test;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

public class MyJaxbJacksonObjectMapper extends ObjectMapper {

public MyJaxbJacksonObjectMapper() {

    this.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
            .setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY)
            .setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
            .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
            .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

    this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }
}

然后在context-configuration(servlet-context.xml)中实例化它:

<mvc:annotation-driven>
    <mvc:message-converters>

        <beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <beans:property name="objectMapper">
                <beans:bean class="com.test.MyJaxbJacksonObjectMapper" />
            </beans:property>
        </beans:bean>

    </mvc:message-converters>
</mvc:annotation-driven>

这样很好!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.