【问题标题】:Lombok @SuperBuilder example with json annotations带有 json 注释的 Lombok @SuperBuilder 示例
【发布时间】:2018-10-10 06:45:16
【问题描述】:

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

谢谢

【问题讨论】:

    标签: java lombok


    【解决方案1】:

    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 一起使用,您必须手动添加构建器类标题并在其上放置 @JsonPOJOBuilder(withPrefix="")。然后,Lombok 将仅生成构建器类的其余部分。这是必要的,因为 Jackson 的默认设置是构建器的 setter 方法具有“with”作为前缀,但 Lombok 的构建器没有任何前缀(而 Lombok 没有并且可能永远不会在这方面可配置)。

    当@SuperBuilder 在 Lombok 1.18.2 中引入时,它是不可定制的(即,您不能手动添加构建器类头)。因此,很难将@SuperBuilder 与 Jackson 一起使用。

    Lombok 1.18.4 对此进行了更改(请参阅 this pull request):@SuperBuilder 现在(至少部分)可自定义,这允许我们添加注释。请注意,@SuperBuilder 生成的代码非常复杂,并且大量加载了泛型。为避免意外弄乱代码,您应该查看 delombok 输出并从那里复制/粘贴类标头。在这里,您需要添加构建器实现类头并在其上添加注解:

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

    请注意,您必须将 SubABuilderImpl 的可见性扩大到至少包私有。

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

    @JsonDeserialize(builder = SubA.SubABuilderImpl.class)
    

    【讨论】:

    • 那么结果,你说目前无法使用@SuperBuilder?
    • 可以用,只是不能和Jackson一起反序列化。
    • Lombok 1.18.4 已经发布,现在允许自定义@SuperBuilders。我用一个可行的解决方案更新了我的答案。
    • 这个解决方案对我有用。唯一的小烦恼是 Eclipse 使用以下语法报告了一些错误:Multiple markers at this line- implements com.company.SubA.SubABuilder&lt;com.company.SubA,com.company.SubA.SubABuilderImpl&gt;.self- The method $fillValuesFrom(C) is undefined for the type SubA.SubABuilder&lt;C,B&gt;- The method $fillValuesFrom(C) of type SubA.SubABuilderBuilder&lt;C,B&gt; must override or implement a supertype method- implements com.company.SubA.SubABuilder&lt;C,B&gt;.self 如果有人对解决这些问题有任何建议,我很想听听。跨度>
    • 首先确保eclipse中安装的Lombok版本与maven/grade中的版本一致。您看到的消息似乎在层次结构中的所有类上都没有 toBuilder=true。
    【解决方案2】:

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

    【讨论】:

    • 我认为你是对的,IntelliJ 插件在生成带有注释的代码时存在问题。 JsonPOJOBuilder 的有趣解决方案。总而言之,我现在将使用与 SuperBuilder 不同的方法。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2020-07-18
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 2023-04-08
    相关资源
    最近更新 更多