How to retrieve JSON response body using URLSession with RapidAPI

I’m working on a Swift iOS app and trying to fetch weather data from an API service. The service gave me sample code that uses URLSession to make GET requests. Here’s what I have so far:

import Foundation

let apiHeaders = [
    "x-rapidapi-host": "weather-service.p.rapidapi.com",
    "x-rapidapi-key": "your_api_key_here"
]

let urlRequest = NSMutableURLRequest(url: NSURL(string: "https://weather-service.p.rapidapi.com/forecast?location=90210")! as URL,
                                   cachePolicy: .useProtocolCachePolicy,
                                   timeoutInterval: 10.0)
urlRequest.httpMethod = "GET"
urlRequest.allHTTPHeaderFields = apiHeaders

let urlSession = URLSession.shared
let task = urlSession.dataTask(with: urlRequest as URLRequest, completionHandler: { (responseData, httpResponse, requestError) -> Void in
    if (requestError != nil) {
        print(requestError)
    } else {
        let serverResponse = httpResponse as? HTTPURLResponse
        print(serverResponse)
    }
})

task.resume()

The problem is that I can see the response headers when I run this code, but I can’t figure out how to access the actual JSON data that comes back from the API. I’m fairly new to iOS development and could use some guidance on extracting the response body content.

The responseData parameter has your JSON payload as raw Data. I’ve worked with RapidAPI endpoints for years - skip JSONSerialization and use JSONDecoder instead. It’s newer and handles Swift types way better.

if let data = responseData {
let jsonString = String(data: data, encoding: .utf8)
print(“Raw JSON: (jsonString ?? “Invalid data”)”)

// For structured parsing
do {
    let decoder = JSONDecoder()
    let weatherResponse = try decoder.decode(WeatherData.self, from: data)
    // Use your decoded object
} catch {
    print("Decoding failed: \(error)")
}

}

Just create a struct that matches your API response. This saved me tons of debugging time vs messing around with dictionaries.

You’re not processing the responseData parameter in your completion handler. That’s where the JSON lives, but you’re ignoring it completely. Add this inside your completion handler after checking for errors:

if let data = responseData {
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data, options: )
print(jsonResponse)
} catch {
print(“JSON parsing error: (error)”)
}
}

This deserializes the raw data into readable JSON. If you need specific values from the response, cast jsonResponse to a dictionary and grab whatever fields you want. I made this exact mistake when I started with APIs - spent forever looking at headers while the actual data sat right there unused.

you’re missing responseData handling. convert it to string first to see what’s coming back - String(data: responseData!, encoding: .utf8) then parse it properly. i always do this when debugging api calls, saves a lot of headaches.