UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Jackson】ObjectMapperであるクラスだけ別のPropertyNamingStrategiesにしたい

カスタマイズしたJackson2ObjectMapperBuilderを介して、ObjectMapperを独自の設定にすることができた

これでどこで使っても同じ設定になるわけだが、悲しいことにある外部APIのレスポンスだけ期待とは違うことに気づいた

具体的にはプロパティ名がLOWER_CAMEL_CASEであることを期待していたが、そのAPIだけUPPER_CAMEL_CASEになっている

先のカスタマイズしたJackson2ObjectMapperBuilderでは、LOWER_CAMEL_CASEになるような設定をしているためうまくマッピングされなかった

当然ながらDIしたObjectMapperに対してUPPER_CAMEL_CASEになるようにオーバーライドしてしまうと、他のAPIでこんどはアンマッチになってしまうので、 このAPIのレスポンスだけに対して行いたい

最速の解決策

UPPER_CAMEL_CASE用のbuilderを作ることも考えたが、もっとも簡単な解決方法は、そのDTO@JsonNamingアノテーションをつけてしまうことだった

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
@Data
public class FooApiResponse {
  private List<Foo> data;

  @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
  @Data
  public static final class Foo {
    private Integer id;
    private String firstName;
    private String url;
  }

これで、このレスポンスだけUPPER_CAMEL_CASEとしてマッピングしてくれる

一点、内部クラスにもアノテーションをつけなければならないことに注意が必要だった

ObjectMapperBuilderをつくる

他の策としてUPPER_CAMEL_CASE用のbuilderをつくることを考えた

Jackson2ObjectMapperBuilderCustomizerにPropertyNamingStrategiesの設定をしているので、Customizerを呼び出して設定を上書きするようなことをしなくてはならない

たぶんこのような感じ

    @Bean
    @Primary
    public ObjectMapper mapper(List<Jackson2ObjectMapperBuilderCustomizer> customizerList,
   ApplicationContext context) {
      Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
      builder.applicationContext(context);
      for (Jackson2ObjectMapperBuilderCustomizer customizer: customizerList) {
        customizer.customize(builder);
      }
      return builder.build();
    }

    @Bean
    @Qualifier("upper")
    public ObjectMapper upperCaseMapper(List<Jackson2ObjectMapperBuilderCustomizer>
   customizerList, ApplicationContext context) {
      Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
      builder.applicationContext(context);
      for (Jackson2ObjectMapperBuilderCustomizer customizer: customizerList) {
        customizer.customize(builder);
      }
      builder.propertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE);
      return builder.build();
    }