public static APINodeList<ProfilePictureSource> parseResponse(
     String json, APIContext context, APIRequest request) {
   APINodeList<ProfilePictureSource> profilePictureSources =
       new APINodeList<ProfilePictureSource>(request, json);
   JsonArray arr;
   JsonObject obj;
   JsonParser parser = new JsonParser();
   try {
     JsonElement result = parser.parse(json);
     if (result.isJsonArray()) {
       // First, check if it's a pure JSON Array
       arr = result.getAsJsonArray();
       for (int i = 0; i < arr.size(); i++) {
         profilePictureSources.add(loadJSON(arr.get(i).getAsJsonObject().toString(), context));
       }
       ;
       return profilePictureSources;
     } else if (result.isJsonObject()) {
       obj = result.getAsJsonObject();
       if (obj.has("data")) {
         try {
           JsonObject paging =
               obj.get("paging").getAsJsonObject().get("cursors").getAsJsonObject();
           profilePictureSources.setPaging(
               paging.get("before").getAsString(), paging.get("after").getAsString());
         } catch (Exception ignored) {
         }
         if (obj.get("data").isJsonArray()) {
           // Second, check if it's a JSON array with "data"
           arr = obj.get("data").getAsJsonArray();
           for (int i = 0; i < arr.size(); i++) {
             profilePictureSources.add(loadJSON(arr.get(i).getAsJsonObject().toString(), context));
           }
           ;
         } else if (obj.get("data").isJsonObject()) {
           // Third, check if it's a JSON object with "data"
           obj = obj.get("data").getAsJsonObject();
           profilePictureSources.add(loadJSON(obj.toString(), context));
         }
         return profilePictureSources;
       } else if (obj.has("images")) {
         // Fourth, check if it's a map of image objects
         obj = obj.get("images").getAsJsonObject();
         for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
           profilePictureSources.add(loadJSON(entry.getValue().toString(), context));
         }
         return profilePictureSources;
       } else {
         // Fifth, check if it's pure JsonObject
         profilePictureSources.add(loadJSON(json, context));
         return profilePictureSources;
       }
     }
   } catch (Exception e) {
   }
   return null;
 }
  public static APINodeList<TargetingProductAudienceSpec> parseResponse(
      String json, APIContext context, APIRequest request) throws MalformedResponseException {
    APINodeList<TargetingProductAudienceSpec> targetingProductAudienceSpecs =
        new APINodeList<TargetingProductAudienceSpec>(request, json);
    JsonArray arr;
    JsonObject obj;
    JsonParser parser = new JsonParser();
    Exception exception = null;
    try {
      JsonElement result = parser.parse(json);
      if (result.isJsonArray()) {
        // First, check if it's a pure JSON Array
        arr = result.getAsJsonArray();
        for (int i = 0; i < arr.size(); i++) {
          targetingProductAudienceSpecs.add(
              loadJSON(arr.get(i).getAsJsonObject().toString(), context));
        }
        ;
        return targetingProductAudienceSpecs;
      } else if (result.isJsonObject()) {
        obj = result.getAsJsonObject();
        if (obj.has("data")) {
          if (obj.has("paging")) {
            JsonObject paging =
                obj.get("paging").getAsJsonObject().get("cursors").getAsJsonObject();
            String before = paging.has("before") ? paging.get("before").getAsString() : null;
            String after = paging.has("after") ? paging.get("after").getAsString() : null;
            targetingProductAudienceSpecs.setPaging(before, after);
          }
          if (obj.get("data").isJsonArray()) {
            // Second, check if it's a JSON array with "data"
            arr = obj.get("data").getAsJsonArray();
            for (int i = 0; i < arr.size(); i++) {
              targetingProductAudienceSpecs.add(
                  loadJSON(arr.get(i).getAsJsonObject().toString(), context));
            }
            ;
          } else if (obj.get("data").isJsonObject()) {
            // Third, check if it's a JSON object with "data"
            obj = obj.get("data").getAsJsonObject();
            boolean isRedownload = false;
            for (String s : new String[] {"campaigns", "adsets", "ads"}) {
              if (obj.has(s)) {
                isRedownload = true;
                obj = obj.getAsJsonObject(s);
                for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
                  targetingProductAudienceSpecs.add(loadJSON(entry.getValue().toString(), context));
                }
                break;
              }
            }
            if (!isRedownload) {
              targetingProductAudienceSpecs.add(loadJSON(obj.toString(), context));
            }
          }
          return targetingProductAudienceSpecs;
        } else if (obj.has("images")) {
          // Fourth, check if it's a map of image objects
          obj = obj.get("images").getAsJsonObject();
          for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
            targetingProductAudienceSpecs.add(loadJSON(entry.getValue().toString(), context));
          }
          return targetingProductAudienceSpecs;
        } else {
          // Fifth, check if it's an array of objects indexed by id
          boolean isIdIndexedArray = true;
          for (Map.Entry entry : obj.entrySet()) {
            String key = (String) entry.getKey();
            if (key.equals("__fb_trace_id__")) {
              continue;
            }
            JsonElement value = (JsonElement) entry.getValue();
            if (value != null
                && value.isJsonObject()
                && value.getAsJsonObject().has("id")
                && value.getAsJsonObject().get("id") != null
                && value.getAsJsonObject().get("id").getAsString().equals(key)) {
              targetingProductAudienceSpecs.add(loadJSON(value.toString(), context));
            } else {
              isIdIndexedArray = false;
              break;
            }
          }
          if (isIdIndexedArray) {
            return targetingProductAudienceSpecs;
          }

          // Sixth, check if it's pure JsonObject
          targetingProductAudienceSpecs.clear();
          targetingProductAudienceSpecs.add(loadJSON(json, context));
          return targetingProductAudienceSpecs;
        }
      }
    } catch (Exception e) {
      exception = e;
    }
    throw new MalformedResponseException("Invalid response string: " + json, exception);
  }