带有 json 注释的 Lombok @SuperBuilder 示例

Lombok @SuperBuilder example with json annotations

有人可以给我提供一个带有 lombok @SuperBuilder 实验注释的工作示例吗?

我无法理解 运行 并且没有代码示例作为文档可用。

目前我的代码如下所示:

超类:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = SubA.class),
  @JsonSubTypes.Type(value = AnotherSub.class)
})
@Getter
@Accessors(fluent = true, chain = true)
@SuperBuilder
public abstract class AbstractA {

    @JsonProperty
    protected final String superProperty;
}

和子类:

@Getter
@EqualsAndHashCode(callSuper = true)
@Accessors(fluent = true, chain = true)
@SuperBuilder
@JsonDeserialize(builder = SubA.SubABuilder.class) // class not found?
@JsonTypeName("SubA")
public class SubA extends AbstractA {

    @JsonProperty
    private final String fieldA;
}

谢谢

2018-11-10 更新:Lombok 1.18.4 发布

2020-10-18 更新:Lombok 1.18.16 发布

Lombok 1.18.16 包含新的 @Jacksonized annotation。有了它,你可以简单地写:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = SubA.class),
  @JsonSubTypes.Type(value = AnotherSub.class)
})
@Jacksonized
@SuperBuilder
// more annotations...
public abstract class AbstractA {

    @JsonProperty
    protected final String superProperty;
}

@Jacksonized
@SuperBuilder
@JsonTypeName("SubA")
// more annotations...
public class SubA extends AbstractA {

    @JsonProperty
    private final String fieldA;
}

这将自动插入所有必要的 Jackson 注释并对生成的构建器进行一些调整。不用再定制了。

对于 1.18.4 和 1.18.12 之间的早期 Lombok 版本,这是要走的路:

要让 Lombok 的 @Builder@SuperBuilder 与 Jackson 一起工作,您必须手动添加构建器 class header 并在其上放置一个 @JsonPOJOBuilder(withPrefix="") .然后 Lombok 将只生成构建器的剩余部分 class。这是必要的,因为 Jackson 的默认设置是构建器的 setter 方法以“with”作为前缀,但 Lombok 的构建器没有任何前缀(在这方面 Lombok 不是也可能永远不会配置)。

在 Lombok 1.18.2 中引入 @SuperBuilder 时,它是不可自定义的(即,您无法手动添加构建器 class header)。因此,与杰克逊一起使用 @SuperBuilder 并不容易。

这在 Lombok 1.18.4 中发生了变化(请参阅 this pull request):@SuperBuilder 现在(至少部分)可自定义,这允许我们添加注释。请注意,@SuperBuilder 生成的代码非常复杂,并且大量加载了泛型。为避免不小心弄乱代码,您应该查看 delombok 输出并从那里查看 copy/paste class header。在这里,您需要添加构建器实现 class header 并在其上放置注释:

@JsonPOJOBuilder(withPrefix="")
static final class SubABuilderImpl extends SubABuilder<SubA, SubABuilderImpl> {
}

请注意,您必须将 SubABuilderImpl 的可见性扩大到至少 package-private。

@JsonDeserialize 注释还必须引用构建器实现 class,而不是抽象构建器:

@JsonDeserialize(builder = SubA.SubABuilderImpl.class)

Eclipse 中的有效解决方案,请注意 Lombok IntelliJ 集成不支持所有功能,因此代码在 Eclipse 和 javac 中编译良好,但 IntelliJ 认为它已损坏但执行代码没有问题。

public static ObjectMapper createObjectMapper() {

    final ObjectMapper mapper = new ObjectMapper();
    mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {

        @Override
        public JsonPOJOBuilder.Value findPOJOBuilderConfig(final AnnotatedClass ac) {
            if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
                return super.findPOJOBuilderConfig(ac);
            }
            return new JsonPOJOBuilder.Value("build", "");
        }
    });

    return mapper;
}

public static void main(final String[] args) throws Exception {
    final ObjectMapper objectMapper = createObjectMapper();

    final String serializedForm = objectMapper.writeValueAsString(SubA.builder().build());
    System.out.println(serializedForm);
    final SubA anA = objectMapper.readValue(serializedForm, SubA.class);
    System.out.println(anA);
}


@Getter
@EqualsAndHashCode(callSuper = true)
@Accessors(fluent = true, chain = true)
@SuperBuilder
@JsonDeserialize(builder = SubA.SubABuilderImpl.class)
@JsonTypeName("SubA")
public static class SubA extends AbstractA {

    @JsonProperty
    private final String fieldA;
}


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = SubA.class)
})
@Getter
@Accessors(fluent = true, chain = true)
@SuperBuilder
public static abstract class AbstractA {

    @JsonProperty
    protected final String superProperty;
}