永恒的龙目岛与杰克逊一起注释

时间:2018-04-24 10:33:38

标签: java json jackson lombok jackson-databind

创建

类的首选方法是什么
  • 不可变
  • 可以使用Jackson
  • 进行序列化/反序列化
  • 人性化且低水平的样板

最好是,我希望这样的工作能够发挥作用:

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

然后将所有字段设为private final。但是,这甚至没有编译(我不知道为什么)。使用

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

将编译但仅产生

InvalidDefinitionException: No serializer found for class

9 个答案:

答案 0 :(得分:16)

您可以使用Lombok的@Builder注释为您的不可变POJO类生成构建器。 但是让杰克逊的反序列化使得Lombok生成的构建器可用是有点棘手的。

示例:

不可变的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);
    }
}

答案 1 :(得分:12)

另一种选择:

是要添加 ConstructorProperties

  • 使用以下行创建一个lombok.config文件in an appropriate locationlombok.anyConstructor.addConstructorProperties = true
  • 在您的课程中添加lombok @Value注释以使其不可变

然后,Jackson的序列化和反序列化将按预期进行。

答案 2 :(得分:3)

尝试为您的pojo使用以下注释集:

@Value
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor

答案 3 :(得分:3)

截至2020年10月15日龙目岛(v1.18.16),您应该只能够使用@Jacksonized批注。

@Jacksonized @Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class JacksonExample {
  private List<Foo> foos;
}

如链接文档中所述,此注释:

  • 配置Jackson使用生成器进行反序列化,
  • 将特定于字段的配置从带注释的类复制到生成的生成器(例如@JsonIgnoreProperties),并且
  • 将构建器方法(例如builder().withField(field)builder.field(field)上使用的Jackson前缀与Lombok中配置的前缀对齐。

答案 4 :(得分:1)

另一种不太冗长的选择:

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

答案 5 :(得分:1)

我已经用这种方式解决了它:

@Value
@Builder(setterPrefix = "with")
@JsonDeserialize(builder = Clazz.ClazzBuilder.class)
public class Clazz {
    private String field;
}

在这种情况下,您必须使用withField(...)之类的构建器方法,这是杰克逊使用的默认行为。

答案 6 :(得分:0)

通过引用answer by Joseph K. Strauss,我提出了以下解决方案。

对我有用的

简单的龙目岛注释看起来像这样。以下注释为您提供了带有生成器的不变类,可以由Jackson进行序列化和反序列化。

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

我更喜欢这种解决方案,因为它不需要额外的Jackson specific annotations和不需要的lombok specific files

答案 7 :(得分:0)

托马斯·弗里奇(Thomas Fritsch)的答案在pom中添加了Jackson Dataformat依赖项之后,与Spring Boot完美配合。

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

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

答案 8 :(得分:0)

为Jackson配置不可变类的最简单方法是使用lombok注释:@Value@Jacksonized

    @Jacksonized
    @Builder
    @Value
    class Foo {

        
    }