Search code examples
jsonswiftapialamofire

Best method to parse consecutive JSON files?


I am importing JSON from a link where each file contains a "next" property with a URL of the next JSON file in it, until it is eventually null and has gone through all the files.

My question is, how can I best import all these consecutive files? as they are all required in a table but the limit is 20 objects per JSON as per the API restriction.

I presume the answer would be to do with looping through the results and stating 'if the count of objects is 20 then increment the URL page number by 1'? then once i hit the final page and have 8 results it will know not to go for another loop? I just cant comprehend how this works in code and where it sits.

Current Request:

open class ApiService: NSObject {

open func getData(completionHandler: @escaping (NSDictionary?, NSError?) -> Void) -> Self {

    let requestUrl = "https://wger.de/api/v2/exercise/?format=json&language=2&status=2&?limit=199"

    Alamofire.request(requestUrl, method: .get, encoding: URLEncoding.default)
        .responseJSON { response in

            switch response.result {

            case .success( let data):
                print("Request was sucessful")
                completionHandler(data as? NSDictionary, nil)

            case .failure(let error):
                print("Request failed with error: \(error)")
                completionHandler(nil, error as NSError?)
            }
    }
    return self
}

EDIT UPDATE: Had a go at applying the code in the comments, this is my current code but I still have issues:

let requestUrl = "https://wger.de/api/v2/exercise/?format=json&language=2&status=2"

open func getData(_URL: NSURL, completionHandler: @escaping (NSDictionary?, NSError?) -> Void) -> Self {

Alamofire.request(requestUrl, method: .get, encoding: URLEncoding.default)
    .responseJSON { response in

        switch response.result {

        case .success(let data):
            print("Request was sucessful")

            let json = data as! [String:Any]

            let results = json["results"] as! NSDictionary; completionHandler(results, nil)

            if let nextURL = json["next"] as? NSURL {self.getData(_URL: nextURL, completionHandler: completionHandler)} else { print(json["next"] as? String)

                print("No next page, we are at the end")
            }

        case .failure(let error):
            print("Request failed with error: \(error)")
            completionHandler(nil, error as NSError?)
        }
}
return self

Solution

  • Updating your Code (I have not compiled it )

    open class ApiService: NSObject {
    
    open func getData(requestUrl: String, completionHandler: @escaping (NSDictionary?, NSError?) -> Void) -> Self {
    
        Alamofire.request(requestUrl, method: .get, encoding: URLEncoding.default)
            .responseJSON { response in
    
                switch response.result {
    
                case .success(let data):
                    print("Request was sucessful")
                    completionHandler(data as? NSDictionary, nil)
    
                case .failure(let error):
                    print("Request failed with error: \(error)")
                    completionHandler(nil, error as NSError?)
                }
        }
        return self
    }
    }
    

    Your Code in View Controller

    override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            let initialURLString = "https://wger.de/api/v2/exercise/?format=json&language=2&status=2"
            getApiData(dataURL:initialURLString)
        }
    
    func getApiData(dataURL: String) {
    
    let _ = apiService.getData(requestUrl: dataURL) {
        (data, error) in
        if let data = data {
            if let results = data["results"] as? [[String:Any]] {
                for result in results {
                    if let exercise = Exercise(dictionary: result) {
                        self.exercises.append(exercise)
                    }
                }
                self.exercisesTableView.reloadData()
            }
            if let nextURL = data["next"] as? String
            {
                print("NEXT URL: \(nextURL)")
                self.getApiData(dataURL:nextURL)
            }
        }
    }
    }