首页 > 解决方案 > 如何使用杰克逊序列化 JSON 字符串中的缺失字段

问题描述

我正在阅读一个 JSON 字符串,其中每个字段都是可选的,我需要从配置中获取值或将其设置为默认值。

说我的 JSON 是 -

{
"action": {
           "onWarning":{
               "alert":{
                      "isEnabled": true,
                    "name": "DVS.sd_service.data-validation.bigdata.warning"
                       }
               },
           "onError":{
             "alert":{
                    "isEnabled": false,
                    "name": "DVS.sd_service.data-validation.bigdata.error"
                    }
               }
         }
}

我读取这个 JSON 的代码是 -

    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    mapper.registerModule(new Jdk8Module());
    JobConfig jobConfig = mapper.readValue(contentJson, JobConfig.class);

下面是我的包装类 -

@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class JobConfig {
    public Optional<AlertConfig> action;
}

@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class AlertWrapper {
    public Optional<Alert> alert;
}

@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class AlertConfig {
    public Optional<AlertWrapper> onSuccess;
    public Optional<AlertWrapper> onWarning;
    public Optional<AlertWrapper> onError;
}

@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Alert{
    public Optional<Boolean> isEnabled;
    public Optional<String> name;
}

现在的目标是阅读,OnError.alert.isEnabled但是如果此字段或整个onError部分不可用,那么我们必须将其设置为默认值True

我为此编写的功能是:-

private Optional<Boolean> getErrorIsEnabled(JobConfig jobConfig ) {
        Optional<Boolean> isEnabled = Optional.empty();
        if(jobConfig.action.isPresent()) {
            if(jobConfig.action.get().onError.isPresent()){
                if(jobConfig.action.get().onError.get().alert.isPresent()) {
                    if(jobConfig.action.get().onError.get().alert.get().isEnabled.isPresent()){
                        isEnabled= jobConfig.action.get().onError.get().alert.get().isEnabled;
                    }
                }
            }
        }
        return isEnabled;
    }

通过这种方式,我可以通过调用上述函数来查找 vale 在配置中是否可用 -

getErrorIsEnabled(jobConfig).orElse(true)

问题是(调用上述函数)这可行,但看起来太难看,无法通过调用函数继续检查每个级别的字段是否可用isPresent()

用户可以完全跳过OnError部分,或action部分,或只是alert部分,或alert.isEnabled部分。必须有更好的方法来实现这一点!对建议或改进持开放态度,或者一起尝试不同的方法。

标签: javajsonjackson

解决方案


您应该做的是为字段创建默认值,例如

private Optional<Boolean> isEnabled = Optional.empty();
private Optional<String> name = Optional.empty();

public Alert(Optional<Boolean> isEnabled , Optional<String> name){
    this.isEnabled=isEnabled;
    this.name=name;
}

对于每个这样的对象 -

private final Alert alertDetail = new Alert(Optional.empty(), Optional.empty());
    private final AlertWrapper alertWrapper = new AlertWrapper(alertDetail);


    private AlertWrapper onSuccess = alertWrapper;
    private AlertWrapper onWarning = alertWrapper;
    private AlertWrapper onError = alertWrapper;

您将必须创建构造函数,因此您必须将您的 lombok 更改为@NoArgsConstructor也使用@Getter @Setter,这样您就可以调用您的对象,如下所示 -

jobConfig.getAction().getOnWarning().getAlert().getIsEnabled().orElse(true)

推荐阅读