Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用lombok builder反序列化Java可选字段?_Java_Jackson_Optional_Lombok_Jackson Databind - Fatal编程技术网

如何使用lombok builder反序列化Java可选字段?

如何使用lombok builder反序列化Java可选字段?,java,jackson,optional,lombok,jackson-databind,Java,Jackson,Optional,Lombok,Jackson Databind,我想反序列化lombok builder中的Java可选字段。下面是我的代码 @JsonDeserialize(builder = AvailabilityResponse.Builder.class) @Getter @ToString @EqualsAndHashCode @Builder(setterPrefix = "with", builderClassName = "Builder", toBuilder = true) public class AvailabilityRespon

我想反序列化lombok builder中的Java可选字段。下面是我的代码

@JsonDeserialize(builder = AvailabilityResponse.Builder.class)
@Getter
@ToString
@EqualsAndHashCode
@Builder(setterPrefix = "with", builderClassName = "Builder", toBuilder = true)
public class AvailabilityResponse {

    private final List<Train> trainDetails;
    private final String name;
    private final Optional<String> detail;

    public static class Builder {

        @JacksonXmlProperty(localName = "TRAIN")
        private List<Train> trainDetails;

        @JacksonXmlProperty(localName = "NAME")
        private String name;

        @JacksonXmlProperty(localName = "DETAIL_TRAIN", isAttribute = true)
        private String detail;

        public AvailabilityResponse build() {
            return new AvailabilityResponse(
                trainDetails, // I have field validation here. if null or empty throwing Exception
                name, // I have field validation here. if null or empty throwing Exception
                Optional.ofNullable(detail)); // This is Optional field
        }
    }   

}    
@JsonDeserialize(builder=AvailabilityResponse.builder.class)
@吸气剂
@托斯特林
@EqualsAndHashCode
@生成器(setterPrefix=“with”,builderClassName=“Builder”,toBuilder=true)
公共类可用性响应{
私人最终名单详情;
私有最终字符串名;
私人最终可选细节;
公共静态类生成器{
@JacksonXmlProperty(localName=“TRAIN”)
私人名单详情;
@JacksonXmlProperty(localName=“NAME”)
私有字符串名称;
@JacksonXmlProperty(localName=“DETAIL\u TRAIN”,isAttribute=true)
私有字符串细节;
公共可用性响应生成(){
返回新的可用性响应(
trainDetails,//这里有字段验证。如果为null或为空,则引发异常
name,//这里有字段验证。如果为null或为空,则引发异常
可选。ofNullable(detail));//这是可选字段
}
}   
}    
如果我像下面那样重写builder方法,则可以反序列化

    private Optional<String> name; // this is static builder class field

        @JacksonXmlProperty(localName = "DETAIL_TRAIN", isAttribute = true)
        public Builder detail(final String theDetail) {
            this.detail = Optional.ofNullable(theDetail);
            return this;
        }   
私有可选名称;//这是静态生成器类字段
@JacksonXmlProperty(localName=“DETAIL\u TRAIN”,isAttribute=true)
公共生成器详细信息(最终字符串详细信息){
this.detail=可选的不可用项(细节);
归还这个;
}   
我在@Builder中使用了setterPrefix=“with”。但是如果我用“with”前缀覆盖上面的方法,它就不起作用了


请有人帮我用它的
Jackson-datatype-jdk8
模块来实现这个

Jackson支持的
可选
。您只需将其添加到
pom.xml
中的
部分即可:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
    <version>2.10.3</version>
</dependency>
该映射器将自动检测
可选
s:如果XML字段有值,它将被包装在
可选
中;如果XML字段为空(即
),则结果将是
可选的.empty()
。(在本例中,您有一个属性;这些属性不能为空。)

Jackson将XML中不存在的字段或属性映射到
null
(或者更准确地说,它只是不调用setter,因此字段值仍然是默认值)。如果在这种情况下还希望有一个空的
可选
,则需要将字段默认值设置为
可选.empty()
,并向该字段添加一个
@Builder.default

最后,lombok可以自动将注释从字段复制到生成的生成器。您需要使用项目根目录中的
lombok.config
文件告诉lombok要复制哪些注释,该文件包含:

lombok.copyableAnnotations += com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty
config.stopBubbling = true
这意味着您根本不需要自定义生成器类:

@JsonDeserialize(builder = AvailabilityResponse.Builder.class)
@Getter
@ToString
@EqualsAndHashCode
@Builder(setterPrefix = "with", builderClassName = "Builder", toBuilder = true)
public class AvailabilityResponse {

    @JacksonXmlProperty(localName = "TRAIN")
    @JsonProperty("TRAIN")
    private final List<Train> trainDetails;

    @JacksonXmlProperty(localName = "NAME")
    @JsonProperty("NAME")
    private final String name;

    @JacksonXmlProperty(localName = "DETAIL_TRAIN", isAttribute = true)
    @JsonProperty("DETAIL_TRAIN")
    @Builder.Default
    private final Optional<String> detail = Optional.empty();
}
我建议将此构造函数设置为私有的,因为

  • 它强制类的用户使用生成器,并且
  • 在公共API中使用
    可选
    s作为参数是不好的风格

请显示您的xml。123455nsmr23@JasonI认为我发现了问题:Jackson在将
@JacksonXmlProperty
注释放置在参数上时无法识别。我认为这是Jackson中的一个bug,因为参数上允许使用注释,并且它适用于
@JsonProperty
。请参阅。解决方法是在字段中放置@JsonProperty。我更新了我的答案。添加@JsonProperty后,它开始工作了。但这看起来很奇怪,因为添加了两次注释和属性名。另外,如果我在非可选字段中有null,我想抛出IllegalArguementException,因为我只有重写静态生成器类。我更新了我的答案,说明了为什么不应该在生成器中进行验证,并描述了一个解决方案。我不明白为什么必须删除
@builder.Default
和默认值赋值
@Builder.Default
会将默认值赋值移动到一个单独的方法中,因此在调用手动构造函数时不会发生对
细节的赋值。
@JsonDeserialize(builder = AvailabilityResponse.Builder.class)
@Getter
@ToString
@EqualsAndHashCode
@Builder(setterPrefix = "with", builderClassName = "Builder", toBuilder = true)
public class AvailabilityResponse {

    @JacksonXmlProperty(localName = "TRAIN")
    @JsonProperty("TRAIN")
    private final List<Train> trainDetails;

    @JacksonXmlProperty(localName = "NAME")
    @JsonProperty("NAME")
    private final String name;

    @JacksonXmlProperty(localName = "DETAIL_TRAIN", isAttribute = true)
    @JsonProperty("DETAIL_TRAIN")
    @Builder.Default
    private final Optional<String> detail = Optional.empty();
}
private AvailabilityResponse(List<Train> trainDetails, String name, Optional<String> detail) {
    this.trainDetails = Objects.requireNonNull(trainDetails);
    this.name = Objects.requireNonNull(name);
    this.detail = Objects.requireNonNull(detail);
}