⛄️

JacksonAnnotationsInsideでカスタムアノテーションを作る

2022/01/02に公開

今触っているライブラリがJacksonを使っているんですがObjectMapperを中に抱え込んでいてまったくカスタマイズできなくて少し困っています。

そのためシリアライズ・デシリアライズをカスタマイズするときは次のようにフィールドにアノテーションを付与していたのですが、同じ型(この例ではLocalDateTime)のフィールドがあるだけ同じようにアノテーションを付与する必要があって気が滅入っていました。

public record Tweet(
    String name,
    @JsonSerialize(using = ToStringSerializer.class)
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    LocalDateTime timestamp) {
}

さすがに改善したいと思って調べてみるとJacksonAnnotationsInsideアノテーションを使うことでJsonSerializeJsonDeserializeをまとめたカスタムアノテーションを作れることがわかりました。

https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations#meta-annotations

試してみましょう。

アノテーションを作ってJsonSerializeJsonDeserializeを付与します。
それからJacksonAnnotationsInsideも付与すれば作成完了です。

package com.example;

import java.lang.annotation.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.annotation.*;
import com.fasterxml.jackson.databind.ser.std.*;
import com.fasterxml.jackson.datatype.jsr310.deser.*;

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = ToStringSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
public @interface LocalDateTimeJacksonAnnotations {
}

動作確認してみましょう。

作成したカスタムアノテーションをフィールドに付与します。

public record Tweet(
    String content,
    @LocalDateTimeJacksonAnnotations LocalDateTime timestamp) {
}

アノテーションがスッキリしました。

次のようなメインクラスを作って実行しましょう。

package com.example;

import java.time.*;
import com.fasterxml.jackson.databind.*;

public class App {
    public static void main(String[] args) throws Exception {
        Tweet tweet = new Tweet(
                "なるほど四時じゃねーの",
                LocalDateTime.parse("2022-01-02T04:00"));
        String json = new ObjectMapper().writeValueAsString(tweet);
        System.out.println(json);
    }
}

出力は次の通りです。

{"content":"なるほど四時じゃねーの","timestamp":"2022-01-02T04:00"}

ちゃんとカスタムアノテーションが仕事してくれましたね。

以上です。

Discussion