I'm getting this deeply nested JSON response from an api that I have no control,
What should be the best way to get to "generalDetails" and then find the first true value under security, address, account and mobile?
{
"info_code": "201",
"info_description": "info description",
"data": {
"status": "here goes the status",
"failure_data": {
"source": "anySource",
"details": {
"data": {
"server_response": {
"generalDetails": {
"security": {
"isAccountLocked": "false"
},
"address": {
"isAddresExists": "true"
},
"account": {
"accountExists": "true",
"isValidAccount": "true"
},
"mobile": {
"mobileExists": "true"
}
}
}
}
}
}
}
}
My request looks like:
@Autowired
private WebClient.Builder webClientBuilder;
String resp = webClientBuilder.build().get().uri(URL)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class).block();
CodePudding user response:
First, build the model, automatic here https://codebeautify.org/json-to-java-converter.
Then read data with the model
.bodyToMono(MyData.class)
Then decide how you want evaluate the requirement find the first true value under security, address, account and mobile
.
What means "first" ? JSON has no natural order without indicating explicity (e.g. field "order": 2).
N.B. "true", "false" of the response are Strings, not booleans.
Once you have the model with data, you may do:
Object firstTrue(GeneralDetails gd) {
// No null checks here
if ("true".equals(gd.getSecurtity().isLockedAccount())) return gd.getSecurtity();
if ("true".equals(gd.getAddress().isAddressExists())) return gd.getAddress();
if ("true".equals(gd.getAccount().isAccountExists()) || "true".equals(gd.getAccount().isAccountValid())) return gd.getAccount();
if ("true".equals(gd.getMobile().isMobileExists())) return gd.getMobile();
return null;
}
CodePudding user response:
https://github.com/octomix/josson
Deserialization
Josson josson = Josson.fromJsonString(
"{"
" \"info_code\": \"201\","
" \"info_description\": \"info description\","
" \"data\": {"
" \"status\": \"here goes the status\","
" \"failure_data\": {"
" \"source\": \"anySource\","
" \"details\": {"
" \"data\": {"
" \"server_response\": {"
" \"generalDetails\": {"
" \"security\": {"
" \"isAccountLocked\": \"false\""
" },"
" \"address\": {"
" \"isAddresExists\": \"true\""
" },"
" \"account\": {"
" \"accountExists\": \"true\","
" \"isValidAccount\": \"true\""
" },"
" \"mobile\": {"
" \"mobileExists\": \"true\""
" }"
" }"
" }"
" }"
" }"
" }"
" }"
"}");
Query
JsonNode node = josson.getNode(
"data.failure_data.details.data.server_response"
".generalDetails.**.mergeObjects().assort().[*]");
System.out.println(node.toPrettyString());
Output
{
"isAddresExists" : "true"
}
If changed isAddresExists
and accountExists
to false
" \"generalDetails\": {"
" \"security\": {"
" \"isAccountLocked\": \"false\""
" },"
" \"address\": {"
" \"isAddresExists\": \"false\""
" },"
" \"account\": {"
" \"accountExists\": \"false\","
" \"isValidAccount\": \"true\""
" },"
" \"mobile\": {"
" \"mobileExists\": \"true\""
" }"
" }"
Output
{
"isValidAccount" : "true"
}
If you only want the key name
String firstTureKey = josson.getString(
"data.failure_data.details.data.server_response"
".generalDetails.**.mergeObjects().assort().[*].keys().[0]");
System.out.println(firstTureKey);
Output
isValidAccount