Spring Bootによって暗黙的に使用されるJackson JSONマッパーをカスタマイズする方法は?


101

私はSpring Boot(1.2.1)を、RESTful Webサービスの構築チュートリアルと同様の方法で使用しています

@RestController
public class EventController {

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

}

上記のように、Spring MVCはEventListオブジェクトをJSONにシリアル化するために暗黙的にJacksonを使用します。

しかし、次のようなJSON形式にいくつかの簡単なカスタマイズを行いたいと思います。

setSerializationInclusion(JsonInclude.Include.NON_NULL)

問題は、暗黙のJSONマッパーをカスタマイズする最も簡単な方法は何ですか?

このブログ投稿で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でこれを機能させる簡単な方法を探しています。


この注釈は挿入されていますか?:@SuppressWarnings({"SpringJavaAutowiringInspection"})
sven.kwiotek

Spring Webも使用している場合は、このObjectMapperを使用するように手動で指示する必要があることに注意してください。それ以外の場合は、構成されない独自のインスタンスが作成されます。stackoverflow.com/questions/7854030/を

回答:


116

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ドキュメントの「Jackson ObjectMapperのカスタマイズ」セクションを参照してください。

Spring Bootの以前のバージョンを使用している場合、Spring Bootにシリアル化の組み込みを構成する最も簡単な方法は、適切に構成された独自のJackson2ObjectMapperBuilderBean を宣言することです。例えば:

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

1
申し分なく、これはうまくいくようです。あなたはそのような方法をどこに置きますか?おそらく、(メインアプリケーションクラスでは@ComponentScan@EnableAutoConfigurationなど)?
Jonik 2015

2
はい。このメソッドは@Configuration、アプリの任意のクラスで実行できます。メインApplicationクラスはそのための良い場所です。
アンディウィルキンソン

2
重要な注意:Jackson2ObjectMapperBuilderクラスは、spring-webコンポーネントの一部であり、バージョン4.1.1で追加されました。
gaoagong

2
@非推奨のsetSerializationInclusion
Dimitri Kopriwa

6
非推奨:ObjectMapper.setSerializationInclusionはJackson 2.7で非推奨になりました... 代わりにstackoverflow.com/a/44137972/6785908 spring.jackson.default-property-inclusion = non_nullを使用してください
so-random-dude

24

私はこの質問に少し遅れて答えていますが、将来誰かがこれが役立つと思うかもしれません。以下のアプローチは、他の多くのアプローチに加えて、最も効果的に機能し、個人的には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()));
    }
}

1
最近のバージョンでは実装しなければなりませんWebMvcConfigurer
ジョアン・ペドロ・シュミット

はい、人々、このソリューションを試してください、ObjectMapperのBeanを提供しようとしましたが、Jackson2ObjectMapperBuilderのBeanを購入しても機能しませんでした。それでも理由がわかりません。追加のカバーが機能しました!
ソマルソマルスキ

23

多くのものがapplicationpropertiesで設定できます。残念ながら、この機能はバージョン1.3でのみ使用できますが、構成クラスを追加できます。

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

[更新:構成build()が実行される前に-methodが呼び出されるため、ObjectMapperで作業する必要があります。]


それが私の一日を救った解決策でした。このメソッドを、構成クラスではなく、RESTコントローラー自体に追加した以外は。
Nestor Milyaev 2017

20

ドキュメントには、これを行うためのいくつかの方法が記載されています。

デフォルトをObjectMapper完全に置き換える場合は@Bean、そのタイプのを定義し、としてマークします@Primary

定義@Beanのタイプでは、Jackson2ObjectMapperBuilderデフォルトの両方をカスタマイズすることができますObjectMapperし、XmlMapper(に使用MappingJackson2HttpMessageConverterし、MappingJackson2XmlHttpMessageConverterそれぞれを)。


2
デフォルトを置き換えずに同じことをするにはObjectMapper?デフォルトと同様にカスタムを維持することを意味します。
soufrk

12

あなたはあなたのブートストラップクラスの中で注釈されている次のメソッドを追加することができます @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;
}

これは、Boot 2.1.3を使用して動作しました。spring.jacksonプロパティは効果がありませんでした。
Richtopia

9

spring.jackson.serialization-inclusion=non_null 私たちのために働いていた

しかし、Spring Bootのバージョンを1.4.2RELEASE以上にアップグレードすると、機能しなくなりました。

今、別のプロパティspring.jackson.default-property-inclusion=non_nullが魔法をやっています。

実際、serialization-inclusion非推奨です。これは私のintellijが私に投げかけるものです。

非推奨:ObjectMapper.setSerializationInclusionはJackson 2.7で非推奨になりました

したがって、spring.jackson.default-property-inclusion=non_null代わりに使用を開始します


4

私は別の解決策を見つけました。

基本的には、 言及されているブログ投稿のステップ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); 
    }
}

コンポーネントがSpringによってスキャンされたパッケージ内にある限り機能します。(@Primary私の場合、使用は必須ではありませんが、なぜ明示しないでください。)

私にとって、他のアプローチと比較して2つの利点があります。

  • これは簡単です。私はジャクソンからクラスを拡張するだけで、Spring固有の高度な機能について知る必要はありませんJackson2ObjectMapperBuilder
  • アプリの別の部分でJSONを逆シリアル化するために同じJackson構成を使用したいので、この方法は非常に簡単new CustomObjectMapper()です new ObjectMapper()

このアプローチの欠点は、カスタム構成がObjectMapper、Spring Bootによって作成または構成されたインスタンスに適用されないことです。
アンディウィルキンソン

うーん、カスタム設定@RestController現在私にとって十分なクラスの暗黙的なシリアル化に使用されています。(つまり、これらのインスタンスはSpring BootではなくSpring MVCによって作成されたということですか?)しかし、ObjectMappersをインスタンス化する必要がある他のケースに遭遇した場合は、Jackson2ObjectMapperBuilderのアプローチを念頭に置いてください!
Jonik、2015

3

Spring Map 2.0.6でObjectMapperをプライマリにしようとすると、エラーが発生したため、Spring Bootが作成したものを修正しました

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

1

私は上記の解決策を見つけました:

spring.jackson.serialization-inclusion = non_null

スプリングブートの1.4.0.RELEASEバージョンからのみ機能します。他のすべての場合、設定は無視されます。

スプリングブートサンプル「spring-boot-sample-jersey」を変更して実験することで、これを確認しました


0

私はSpring Bootを求める質問を知っていますが、私がほぼ一日中検索しているように、Spring以外のBootでこれを行う方法を探している多くの人々を信じています。

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