3
\$\begingroup\$

I have a URL which I am executing it and it is returning the below string as a JSON response. I am using GSON to parse JSON.

In the below JSON, "resourceId" contains an IP address.

{
   "status":{
      "code":"200",
      "msg":"ok",
   },
   "hasmore":true,
   "count":1000,
   "result":[
      {
         "_type":"Calculate",
         "resourceId":"1.2.3.4",
         "_oid":"522b216"
      },
      {
         "_type":"Calculate",
         "resourceId":"5.6.7.8",
         "_oid":"53cea4ad1"
      },
      {
         "_type":"Calculate",
         "resourceId":"9.10.11.12",
         "_oid":"51f98cce1c12c6"
      }
   ],
   "pagination":{
      "cursor":[
         "",
         "545b3bba43a2",
         ""
      ],
      "limit":[
         10000,
         1000,
         1000
      ],
      "skipEmptyPage":false
   },
   "next":{
      "method":"GET",
      "url":"/urlB"
   }
}

Now from the above JSON response, I need to extract all the resourceId values and populate it into a List<String>.

In my above JSON string, there is a property called "hasmore" and in all the JSON response this field will be there always so if "hasmore" is true, then it means there are more IP Address which will be there in another URL and that URL is present in "next" JSON object in the same JSON response at the bottom so I need to execute that URL and get the JSON response back and that response will be similar to what I have above so populate the IP address into the same list and keep on doing this until you see "hasmore" is false.

In general, I will have original URLA which I will execute it and get the JSON response back which will look like as shown above, parse that JSON populate all the resourceId into a List and then check if "hasmore" is true, then it means there will be another URL at the bottom which is URLB so now execute this URL again, get the JSON response back which will be similar to what I have above and then keep on populating resourceId into the same list and again check if "hasmore" is true or not. Keep on doing this until you see "hasmore" is false.

In short, ips list should have all the IP Address in it since JSON response is coming back as paginated.

I have got the below code working fine:

public static List<String> getListOfIps(String alias) {
    List<String> ips = new ArrayList<String>();
    String url = null;
    boolean hasMore = true;
    try {
        // original url
        url = getURL(alias);
        while (hasMore) {
            String response = getJsonResponse(url);

            // parse response
            if (response != null) {
                JsonElement jelement = new JsonParser().parse(response);
                JsonObject jobject = jelement.getAsJsonObject();

                hasMore = jobject.get("hasmore").getAsBoolean();

                JsonArray jarray = jobject.getAsJsonArray("result");
                if (hasMore) {
                    url = "http://machine.vip.domain.com/ppt" + jobject.getAsJsonObject("next").get("url").getAsString();
                }

                for (JsonElement type : jarray) {
                    ips.add(type.getAsJsonObject().get("resourceId").getAsString());
                }
            }
        }
    } catch (Exception e) {
        // log an exception using logger
    }
    return ips;
}

I am opting for code review for this method to see whether there is any better way of doing this.

\$\endgroup\$
2
  • \$\begingroup\$ Any chance you could be sent into an infinite loop? urlA -> urlB -> urlA for example? \$\endgroup\$
    – mjolka
    Dec 18, 2014 at 4:15
  • \$\begingroup\$ @mjolka No that will not happen. \$\endgroup\$
    – arsenal
    Dec 18, 2014 at 5:32

1 Answer 1

2
\$\begingroup\$

Have the following POJOs

class Result {
    private String resourceId;
}

class Next{
    private String url;
}

class Response{
    private boolean hasMore;
    private List<Result> result;
    private Next next;
}
// If other fields are required add them.
// Have their getters/setters.
// Have the hashCode,equals,toString

Your getListOfIps() could look like this:

List<String> ips = new ArrayList<String>();
Response response = null;
String url = getURL(alias);
do{
    String responseJson = getJsonResponse(url);
    try{
        response = new Gson().fromJson(responseJson , Response.Class);
    } catch( // Json Exceptions thrown by this function){
        // Log the exception and handle it .
    }
    // Check if response and response.result is non null
    // Loop through and extract the non-null resourceId
    // update url
    if(response.hasMore && (response.next!=null) && (response.next.url.length()>0)){
        url= response.next.url;
    }else{
        url = null;
    }
  } while(url);

The code is more of a "steps to follow". Hope it helps.
Try the code and you can post the updated code if its better.
For Gson help follow this link.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for suggestion. Is there any reason of using url in the while loop for check? Can we not use hasMore boolean to do that? \$\endgroup\$
    – arsenal
    Dec 21, 2014 at 18:05
  • \$\begingroup\$ it may so happen that hasMore is true but url may be null or empty. So just a safe check. You can choose otherwise. \$\endgroup\$
    – thepace
    Dec 21, 2014 at 19:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.