web-dev-qa-db-ja.com

Jacksonによる不変のLombok注釈付きクラス

あるクラスを作成する好ましい方法は何ですか

  • 不変
  • Jacksonでシリアル化/逆シリアル化できます
  • 人間が判読できる低レベルの定型文

できれば、私はこのようなものが機能するのが好きだろう:

@Data(onConstructor = @__(@JsonCreator))

そして、すべてのフィールドがprivate final。ただし、これはコンパイルすらしません(その理由はわかりません)。を使用して

@AllArgsConstructor(onConstructor = @__(@JsonCreator))

コンパイルしますが、生成されるのは

InvalidDefinitionException: No serializer found for class
11

別の代替手段:

追加することですConstructorProperties

  • lombok.config file 適切な場所に 行:lombok.anyConstructor.addConstructorProperties = true
  • ロンボクを追加@Value不変にするためのクラスへの注釈

その後、Jacksonによるシリアル化と逆シリアル化は期待どおりに機能します。

15
robSE13

Lombokの _@Builder_ アノテーションを使用して、不変のPOJOクラスのビルダーを生成できます。しかし、Lombokで生成されたビルダーをJacksonのデシリアライゼーションで使用できるようにするのはやや注意が必要です。

  • 使用するビルダークラスをJacksonに伝えるには、POJOクラスに @JsonDeserialize(builder = ...) の注釈を付ける必要があります。
  • ビルダークラスに @JsonPOJOBuilder(withPrefix = "") アノテーションを付けて、そのセッターメソッドが行うことをJacksonに伝える必要がありますnotwithで始まります。

例:

不変のPOJOクラス:

_@Data
@Builder(builderClassName = "PointBuilder")
@JsonDeserialize(builder = Point.PointBuilder.class)
public class Point {

    private final int x;

    private final int y;

    @JsonPOJOBuilder(withPrefix = "")
    public static class PointBuilder {
        // Lombok will add constructor, setters, build method
    }
}
_

POJO outline

以下は、シリアライゼーション/デシリアライゼーションを検証するためのJUnitテストです。

_public class PointTest extends Assert {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void testSerialize() throws IOException {
        Point point = new Point(10, 20);
        String json = objectMapper.writeValueAsString(point);
        assertEquals("{\"x\":10,\"y\":20}", json);
    }

    @Test
    public void testDeserialize() throws IOException {
        String json = "{\"x\":10,\"y\":20}";
        Point point = objectMapper.readValue(json, Point.class);
        assertEquals(new Point(10, 20), point);
    }
}
_
16
Thomas Fritsch

あまり冗長ではない別の代替手段:

@Data
@Setter(AccessLevel.NONE)
public class Clazz {
    private String field;
} 

もちろん、フィールドを直接変更するプライベートメソッドを使用することもできますが、@ Data POJOに実際のコードが含まれる可能性は非常に低いため、このようなことが起こらないようにします。

免責事項:これには、通常のJavaコードにオブジェクトを作成させないという副作用(おそらく有益)があります。ミューテーターを持たないデフォルトのコンストラクターしかないためです。通常の構築を可能にするには、さらに2つの注釈が必要です。

@Data
@AllArgsConstructor
@NoArgsConstructor
@Setter(AccessLevel.NONE)
public class Clazz {
    private String field;
} 
3

Joseph K. Straussによる回答 を参照することで、次の解決策を思いつきました。

私のために働いたプレーンなロンボク注釈はこのように見えます。次のアノテーションは、Jacksonがシリアライズおよびデシリアライズできるビルダーを備えた不変のクラスを提供します。

    @Data
    @Setter(AccessLevel.NONE)
    @Builder(toBuilder = true)
    @AllArgsConstructor
    @NoArgsConstructor(access = AccessLevel.PRIVATE)
    public class Clazz {
        private String field;
    } 

追加の Jackson固有の注釈 および追加の lombok固有のファイル を必要としないため、このソリューションが好ましい

2
Streamline27