SpringでのObjectMapperの構成


91

私の目標は、objectMapper注釈が付けられた要素のみをシリアル化するようにを構成すること@JsonPropertyです。

そうするために、私はオブジェクトマッパーを構成する方法を説明するこの説明に従いました。

ここで説明するように、カスタムオブジェクトマッパーを含めました。

ただし、クラス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));
    }
}

サーブレット.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();
    }
}

回答:


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
boot

10
ねえ、みんな。java configでobjectMapperという名前のBeanを宣言すると、例に示されているように、このBeanはSpring Bootによって無視されるため、\ @を配置しても、そのような名前のBeanはすでにシステムに登録されているという問題に直面しました。その上に一次注釈。この問題を修正するには、jsonObjectMapperなどの別の名前でBeanを登録し、\ @ Primaryアノテーションでマークする必要があります
Demwis 2018

Spring Bootを使用していない場合は、私の回答を参照しください。
ヤマネ

質問:クラスに名前を付ける必要がありJacksonConfigurationますか?これは、このクラスをJacksonの構成クラスとして使用するようにSpring Bootに指示する自動魔法の方法ですか?
マルコ・スッラ

使っても本当に効くの@EnableWebMvc?私は疑っています...私の答えを参照しください:なぜ@EnableWebMvcの使用が問題になるのですか?
adrhc

25

これは、私がSpring 3.1を使用しているためかもしれません(あなたの質問が指定したSpring 3.0.5の代わりに)が、SteveEastwoodの答えは私にはうまくいきませんでした。このソリューションはSpring3.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" />

この春3.1とジャクソン2.xのを使用するための助け:stackoverflow.com/questions/10420040/...
アラムKocharyan

有用!Spring 3.0から3.2へのアップグレード時に、カスタムObjectMapperを登録するためにこのアプローチを採用する必要がありました。以前は、MappingJacksonJsonView Beanを定義するときにobjectMapperプロパティを設定していましたが、機能しなくなりました。これは
DavidEasley18年

20

ありorg.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean、長い時間のため。Spring Bootの1.2リリース以降、JavaConfigorg.springframework.http.converter.json.Jackson2ObjectMapperBuilder用があります。

文字列ブートの構成は、次のように単純にすることができます。

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

inclasspath:application.propertiesまたは@Configurationクラス内のJavaコード:

@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 Bootjackson構成は無視されます。
ジョン

1
テストはしていませんが、@ EnableWebMvcでは機能しないと確信しています(Spring Bootを使用しているかどうかに関係なく)。どうして?WebMvcConfigurationSupport(DelegatingWebMvcConfigurationはWebMvcConfigurationSupportを拡張します)を参照してくださいJackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json()
adrhc

16

私はジャクソンでこれを使用しました2.xのと春3.1.2+

サーブレット-context.xml:

ルート要素は<beans:beans>であるため、設定によっては、これらの要素の一部を削除beansして追加mvcする必要がある場合があります。

    <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>を掘り下げて4時間以上費やしましたが、単にコンバーターを検出しませんでした。あなたの答えを試してみました、ついにそれはうまくいきます!
snowindy 2013

1
アノテーションを使用するにはObjectMapper@Componentおよびとして拡張するカスタムマッパーにアノテーションを付けることができます@Primary。これは、Springリファレンスガイドで推奨されているアプローチであり、私にとっては問題なく機能しました。
OlgaMaciaszek 2015

9

カスタムシリアライザーを登録するためのカスタムObjectMapperを追加したい場合は、私の答えを試してください。

私の場合(Spring3.2.4およびJackson2.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

Spring4.1.6とJacksonFasterXML2.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の悲惨なb / cであるObjectMapperをカスタマイズできないという問題がありました。これに出くわしてよかったです。
エヴァンホワイト

3

Spring Boot2.2.xでは、次のように構成する必要があります。

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

Kotlin:

@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:[COM / Config.class]クラスパスリソースに'customObjectMapper'メソッドで定義された-_halObjectMapper: defined in null
Angshuman Agarwalさん

1
そして、これはSpringBootでのみ機能します。プレーンなSpringWebではありません。
ヤマネ

2

プレーンなSpring-Webでメッセージコンバーターを構成するには、この場合はJava 8 JSR-310 JavaTimeModuleを有効にするために、最初にクラスに実装WebMvcConfigurerしてから@ConfigurationconfigureMessageConvertersメソッドをオーバーライドする必要があります。

@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構成で定義されたカスタムを登録できます。


私は、ObjectMapperをSpringBootを介して注入および構成することを望んでいます。
ConstantinoCronemberger19年

1
もちろん、SpringBootを使用している場合。これはSpringBootの質問ではありませんでした。
ヤマネ

はい、SpringWebをSpringBootで使用する場合、Spring Bootが提供するObjectMapperを使用しないことに気付くのは興味深いことです。そのため、この質問にたどり着きました。
ConstantinoCronemberger19年

これにより、すべてのデフォルトのメッセージコンバータがクリアされます。私は誰もこれを望んでいないと確信しています。解決策については私の答えを参照しください。
adrhc

メッセージコンバーターを拡張したい場合extendMessageConvertersSpringのドキュメントに従って、正しい解決策はオーバーライドすることです。しかし、カスタマイズが必要なだけなので、私はそれを必要としませんでしたMappingJackson2HttpMessageConverter
ヤマネ

1

Spring3.2.4とJacksonFasterXML2.1.1を使用しています。

マップされたオブジェクトの各属性の明示的な注釈を処理するカスタムJacksonObjectMapperを作成しました。

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>

これは問題なく動作します!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.