Home > Software design >  Deeply nested JSON response from third party
Deeply nested JSON response from third party

Time:10-17

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
  • Related