带有 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;
}
有人可以给我提供一个带有 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;
}