Scott M
Scott M

Reputation: 187

How to access JSON response within URLSession of HTTP Post request?

I'm making an http post request within the XCTest framework in Xcode for a simple UI test for my app. Within the request, the response is returned. I can't access that response outside of the URLSession task, and I need to because it contains a JWT that must be decoded and used for another http post request.

I've tried researching how to do this, but it is hard to know the right path as I am a beginner in Swift. I've tried creating a new json object and assigning that response to it outside of the URLSession, but it just says that it can't find that response, it is outside of scope.

// make HTTP request
let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data, error == nil else {
        print(error?.localizedDescription ?? "No data")
        return
    }
    let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
    if let responseJSON = responseJSON as? [String: Any] {
        print(responseJSON)
    }
}
task.resume()
let response = responseJSON as! [String:Any]

The expected results are that I now have my response object outside of the http request and I can then decode it. The actual results is the error:

Use of unresolved identifier 'responseJSON'

Upvotes: 0

Views: 1243

Answers (1)

Scriptable
Scriptable

Reputation: 19750

The request your making is asynchronous. So when you run the line...

let response = responseJSON as! [String:Any]

the network request hasn't finished yet. So you would normally use a completion handler that will be called when the network returns

Here is an example playground:

//: Playground - noun: a place where people can play
import PlaygroundSupport
import UIKit

PlaygroundPage.current.needsIndefiniteExecution = true

func postSomeData(completion: @escaping ([String: Any]?, Error?) -> Void) {
    // setup request
    let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")
    let request = URLRequest(url: url!)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print(error?.localizedDescription ?? "No data")
            completion(nil, error)
        }
        let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
        if let responseJSON = responseJSON as? [String: Any] {
            completion(responseJSON, nil)
        }
    }
    task.resume()
}

postSomeData() { response, error in
    print(response, error)
    PlaygroundPage.current.finishExecution()
}

Output:

Optional(["id": 1, "title": delectus aut autem, "completed": 0, "userId": 1]) nil

I would also suggest that you use Codable for parsing and mapping the JSON response. Here is an intro to using Codable but there are lots of resources available online on the subject.

Upvotes: 1

Related Questions