Reputation: 115
I am reading a JSON String where every field is optional and i need to either get the values from config or set it to a default value.
Say my JSON is -
{
"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"
}
}
}
}
And my code to read this JSON is -
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.registerModule(new Jdk8Module());
JobConfig jobConfig = mapper.readValue(contentJson, JobConfig.class);
And below are my wrapper classes -
@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;
}
Now the objective here is to read OnError.alert.isEnabled
however if this field or the entire onError
part is not available then we have to set it to default True
The function i have written for this is :-
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;
}
This way i get to find if the vale is available in config by calling the above function -
getErrorIsEnabled(jobConfig).orElse(true)
The problem is (calling the above function) this works but looks way too ugly to keep on checking if the fields are available or not at every level by calling the isPresent()
funtion.
The User can entirely skip the OnError
Part, or action
Part, or just the alert
part, or the alert.isEnabled
part. There has to be a better way to acieve this! Open to suggestions or improvements or try a different approach alltogether.
Upvotes: 1
Views: 916
Reputation: 596
What you should do is create default values for the fields like
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;
}
And for every Object like this -
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;
You will have to create constructor so you will have to change your lombok to @NoArgsConstructor
also use @Getter @Setter
so you can call your objects like below -
jobConfig.getAction().getOnWarning().getAlert().getIsEnabled().orElse(true)
Upvotes: 1