Passing protocol into function and returning the protocol through a completion handler (JSONDecoder.decode)

good morning, I have some code written below that is an excerpt from a project where the primary objective is to become more familiar with networking in swift4/iOS and to build more intuition and comfort with completion handlers and closures. My intentions with this program were to create a generic of sorts where I could pass any object into JSONDecoder() as long as it conformed to decodable/codable. For example, I wanted to write something similar to this, so I could make any struct/class and as long as it conforms to codable/decable I would be able to pass it into the function and have JSONDecoder().decode, work its magic and spit that data into the completion handler so I can use it however I want.

typealias jsonTaskCompletionHandler = (_ decodableObject: Decodable) -> Void

func getData(with url : String, completionHandler completion: @escaping jsonTaskCompletionHandler){
let newURL = URL(string: url)
self.session.dataTask(with: newURL!) { (data, _, _) in
guard let data = data else {return }
print(data)
do {
    let jsonData = try JSONDecoder().decode(decodableObject.self, from: data)
    return completion(decodableObject)
} catch {
    print("decoding error")
}
}.resume()
}

instead, I’m hardcoding the type ‘jsonStructure’ to make it work.

typealias jsonTaskCompletionHandler = (jsonStructure) -> Void

func getData(with url : String, completionHandler completion: @escaping jsonTaskCompletionHandler){
let newURL = URL(string: url)
self.session.dataTask(with: newURL!) { (data, _, _) in
guard let data = data else {return }
print(data)
do {
    let jsonData = try    JSONDecoder().decode(jsonStructure.self, from: data)
    return completion(jsonData)
} catch {
    print("decoding error")
}
}.resume()

}
@IBAction func getData(_ sender: UIButton) {
print("button press")
let networkCL = networkClient()
networkCL.getData(with: "someURL") { (objectThatConformsToCodable)   in
print(objectThatConformsToCodable)
}

}

To make the question more clear. I want to pass any data structure/Object that conforms to codable into JSONDecoder().decode and have the completion handler return the JSON data as an instance of the object that is conforming to codable, instead I’m hard coding the specific data type into

data = JSONDecoder.decode(dataType.self) 
completion(data)

whereas I’d just like to pass in
data = JSONDecoder.decode(anyDataStructureThatIsCodable.self)
completion(data)

Any thoughts? Thanks in advance

You don’t mention why you’re having a hard time. The following example might help you get a view of what you want:

func foo<T: Codable>(_ completion: (T) -> ()) {
    ...
    let obj = JSONDecoder.decode(dataType.self, from: data) 
    completion(obj)
} 

you can also use a generic typealias:

typealias jsonTaskCompletionHandler<T: Codable> = (T) -> ()

func foo<T: Codable>(_ completion: jsonTaskCompletionHandler<T>) {

All you have left to do is guarantee that dataType conforms to Codable

Thanks a lot!