JSON, Swift, HTTP Headers and API’s
EDIT 2020: I’ve now taken a back seat from Swift and have gone all in on React Native, Laravel & Vue — lukecurtis.me if you’re looking for more tech goodies
I’d like to take my previous post one step further.
What we had before was essentially a rudimentary query to grab a URL, the data and parse it to JSON.
But before all that sometimes we’ll need to send a header request to our API server so it knows to return a JSON response instead of a HTML response for example and it’s actually relatively simple.
However we need to change a few things about our code first. As always, full code at end of the article.
Remember, here is the JSON we’ll be expecting back from our server.
[
{
"id": 1,
"name": "Red"
},
{
"id": 2,
"name": "Blue"
},
]
Ok, so we’re gonna do a bit more this time. As in the last post, your playground starts like so;
//: Playground - noun: a place where people can playimport Foundation
import XCPlayground
import PlaygroundSupport
import UIKit
PlaygroundPage.current.needsIndefiniteExecution = truestruct Colours: Codable {
let name: String
let id: Int func getString() {
print( "Name: \(name), Id: \(id)" )
}
}var Colours = [Int: Colours]()
We’ve got our struct, and our dictionary where we’re gonna store our API request.
Now we’re gonna go ahead and start configuring our URL query to our server.
let urlString = "http://example.test/colours"let session = URLSession.sharedlet url = URL(string: urlString)!var request = URLRequest(url: url)
It’s the same URL, but we’re using a URLSession and URLRequest object to help us change some details about the data we’ll be asking from the server.
Our URL string is just the URL we need.
Our session
variable is actually our ‘tunnel’ if you like to our endpoint. We’ll be sending it a request later.
The url
variable is us casting our urlString to a URL object, ready for the request to receive it.
Finally the request
variable takes the url we just parsed and packages it up so it’s ready to be sent down our session tunnel
Here the important bit — we need to attach a header to our outgoing request to let the server know we are expecting a JSON response.
request.addValue("application/json", forHTTPHeaderField: "Accept")
What we’ve done is added an additional part to our request and that is a standard HTTP header. You can put anything here you like usually. API tokens maybe.
This is where we deviate a little bit from the previous post, this next block of code shows just the logic involved in grabbing the JSON and sending it back, not parsing it to our dictionary.
session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) inif let data = data{
do{
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let object = json as? [Any] {
print(object)
//logic goes here for looping through the JSON
}
} } catch {
print(error)
}
}
}).resume()
See that first line? We’re using the session
variable and assigning it a task basically. Send the request, return the data — you’ll need the resume bit at the end of code block to ensure it keeps running at every stage of it’s request cycle.
We then check that there was some meaning data returned from our endpoint and parse it like we did previously into a serialisable JSON object
Now we can loop through it like we did before. Place this code where I added the comment in the previous code block for the logic for looping
for anItem in object as! [Dictionary<String, AnyObject>] { let colourName = anItem["name"] as! String let colourID= anItem["id"] as! Int let colour = Colour(name: colourName, id:colourID) colours[colourID] = colour colours[coloursID]?.getString()}
And there you have it, using an API endpoint in Swift with headers. No frameworks needed here for stuff this basic thankfully!