lombokとJSONICでJSONHintアノテーションが動作しない場合の対処

JSONICとlombok併用時に@JSONHintアノテーションが上手く動作しなかったので、その回避策に関するメモ。

使用バージョン

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
</dependency>

<dependency>
    <groupId>net.arnx</groupId>
    <artifactId>jsonic</artifactId>
    <version>1.3.10</version>
</dependency>

現象と回避策

サンプルとして以下の形式の日付文字列を含むJSONをパースしたい、とする。

String json = "{dateTime: \"2018-03-29T11:22:33.123+09:00\"}";
SampleData s = JSON.decode(json, SampleData.class);

lombokを使用するクラスはこんな感じ。

import java.time.LocalDateTime;

import lombok.Data;
import net.arnx.jsonic.JSONHint;

@Data
public class SampleData {
    @JSONHint(format="yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ")
    private LocalDateTime dateTime;
}

これは以下のような例外となり@JSONHintアノテーションが有効になっていないことがわかる。

Exception in thread "main" net.arnx.jsonic.JSONException: {dateTime=2018-03-29T11:22:33.123+09:00} は class asdf.asdfasd.SampleData に変換できませんでした: $.dateTime
    at net.arnx.jsonic.JSON$Context.convertInternal(JSON.java:1775)
    at net.arnx.jsonic.JSON.parse(JSON.java:1155)
    at net.arnx.jsonic.JSON.parse(JSON.java:1130)
    at net.arnx.jsonic.JSON.decode(JSON.java:665)
    at asdf.asdfasd.App.main(App.java:15)
Caused by: java.time.format.DateTimeParseException: Text '2018-03-29T11:22:33.123+09:00' could not be parsed, unparsed text found at index 23
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1952)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)

これの原因だが、https://ja.osdn.net/projects/jsonic/ticket/35184 にJSONICはgetter/setterがある場合はそちらのアノテーションを優先する、とある。lombokはgetter/setterを自動生成するが、そちらには@JSONHintが無いので、このような状況になる。

というわけで回避策として、対象のプロパティについては自前でgetter/setterを定義してしまうことにした。

@Data
public class SampleData {
    /* このプロパティのgetter/setterは不要なので自動生成を抑制 */
    @Getter(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    private LocalDateTime d;

    public LocalDateTime getDateTime() {
        return d;
    }

    @JSONHint(format="yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ")
    public void setDateTime(LocalDateTime dateTime) {
        this.d = dateTime;
    }
}

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.