JSON Parsing in Swift

Handle JSON Response with Codable Protocol in Swift 4

Anand Nimje
Feb 10, 2018 ยท 7 min read

JSON commonly we are using for send and receive data from web service. We can use this easily in our Swift application. Most of the application fully based on JSON. If your application is communicating with web service API then it will return in response to Dictionary(Object), Array, String, Bool, Number. We need to keep in mind before creating model class what type of response will come from web service, based on response we will create the Model class. In this topic, will cover most of the part related parsing from basic to advance level. ๐Ÿš€

Initially, it was a hard task for me understanding JSON parsing. After that, i realize it was nothing for me. Itโ€™s very easy to use. Only need to understand response type. Thats the main thing. ๐Ÿ™‚

Getting Start with Network Request, URLSession

Before starting code we need to check our web Api by hitting in browser -

JSON Response

Now we got the response in web browser, let do some coding in Xcode create new project for JSON parsing -

  • Add inside your projectโ€™s plist open as a source
open your projectโ€™s plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
  • Now make network request with URLSession for web API

We are making the request with web API are handling data and Error which will become the response. I am using here JSONSerialization built-in Foundation framework it will convert JSON data to foundation object.

In this part, i have used testing API from JSONPlaceholder.

guard let url = URL(string: โ€https://jsonplaceholder.typicode.com/todos") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do{
//here dataResponse received from a network request
let jsonResponse = try JSONSerialization.jsonObject(with:
dataResponse, options: [])
print(jsonResponse) //Response result
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
  • Response from web API in JSON format look like this. Now we need to take values from response. Here our response coming in JSON Array .
[
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
}
]
  • Now deal with JSON response object
guard let jsonArray = jsonResponse as? [[String: Any]] else {
return
}
print(jsonArray)
//Now get title value
guard let title = jsonArray[0]["title"] as? String else { return } print(title) // delectus aut autem

Lets try to print all title keys values -

Currently, our JSON response is Array of Dictionary ([[String: Any]]). So we are taking Dictionary from every index of Array with the help of for loop. After getting Dictionary accessing values with the keys.

for dic in jsonArray{
guard let title = dic["title"] as? String else { return }
print(title) //Output
}

Now we can create Userstructure for data handling. In response we are getting different types of values Int, String, Boolean based on values i chose here my model structure for response manage.

struct User {
var userId: Int
var id: Int
var title: String
var completed: Bool
init(_ dictionary: [String: Any]) {
self.userId = dictionary["userId"] as? Int ?? 0
self.id = dictionary["id"] as? Int ?? 0
self.title = dictionary["title"] as? String ?? ""
self.completed = dictionary["completed"] as? Bool ?? false
}
}

Use Model for handle JSON response -

var model = [User]() //Initialising Model Array
for dic in jsonArray{
model.append(User(dic)) // adding now value in Model array
}
print(model[0].userId) // 1211

Cool ๐Ÿ˜Ž , Now you know something about JOSN parsing right ? ๐Ÿ˜ƒ

Letโ€™s make this same code more swifty with FlatMap -

var model = [User]()
model = jsonArray.flatMap{ (dictionary) in
return User(dictionary)
}
print(model[0].userId)
//make more simple
model = jsonArray.flatMap{ return User($0)}
//One more time
model = jsonArray.flatMap{User($0)}
//Or
model = jsonArray.flatMap(User.init)
//Output
print(model[0].userId) // 1211

Yeah ๐Ÿ‘, Lets do more something.


Codable Protocol

This is the new protocol introduced by Apple in Swift 4 can provide Encodable and Decodable built-in feature. It will make JSON parsing easier. It can convert itself into and out of an external representation.

Codable model looks like this. Its pretty easy to understand in a very less code we can manage it.

This is the codable model sample I showed you here. You need to make your own structure model based on your JSON response.

struct User: Codable{
var userId: Int
var id: Int
var title: String
var completed: Bool
}

JSON Parsing with JSONDecoder

After making a network request. Converting web application response raw data into Array Model.

The rest of the JSON network request will be same for this process. Only we need to handle network response Data for JSONDecoder. No major changes for this protocol.

do {
//here dataResponse received from a network request
let decoder = JSONDecoder()
let model = try decoder.decode([User].self, from:
dataResponse) //Decode JSON Response Data
print(model)
} catch let parsingError {
print("Error", parsingError)
}

Why I have used model [User].self because we are getting the response in Array format if your response will get in Dictionary only then

Output from network request โ€”

 {
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}

We need to use our model class like User.self for Dictionary response -

do {
//here dataResponse received from a network request
let decoder = JSONDecoder()
let model = try decoder.decode(User.self, from:
dataResponse) //Decode JSON Response Data
print(model.userId) //Output - 1221
} catch let parsingError {
print("Error", parsingError)
}

Custom key names

We can modify our codable key with custom String keys but it supposes to match with your JSON response keys. Otherwise you will get error message -

Error Message in bottom

Adding custom keys for Codable model -

struct User: Codable{
var userId: Int
var id: Int
var title: String
var completed: Bool
//Custom Keys
enum
CodingKeys: String, CodingKey {
case userId
case id = "serviceId" //Custom keys
case title = "titleKey" //Custom keys
case completed
}
}

Lets make code more Swifty. I made here initialisation process through the extension of the model. The CodingKeys enum will confirm with CodingKey protocol.

struct User: Codable {
var userId: Int
var id: Int
var title: String
var completed: Bool
}
extension User{
enum CodingKeys: String, CodingKey {
case userId
case id
case title
case completed
}
}

Complex JSON Parsing with Codable Protocol

Now we having complex JSON which having Dictionary, Array

{
"branch": {
"subject": 5,
"total_students": 110,
"total_books": 150
},
"Subject": [
{
"subject_id": 301,
"name": "EMT",
"pratical": false,
"pratical_days": [
"Monday",
"Friday"
]
},
{
"subject_id": 302,
"name": "Network Analysis",
"pratical": true,
"pratical_days": [
"Tuesday",
"Thursday"
]
}
]
}

Struct Model for this JSON Response. I have written model like this -

struct Students : Codable {
struct Branch : Codable {
let subject: Int
let totalStudents: Int
let totalBooks: Int
private enum CodingKeys : String, CodingKey {
case subject
case totalStudents = "total_students"
case totalBooks = "total_books"
}
}
struct Subject : Codable {
let subject_id: Int
let name: String
let pratical: Bool
let pratical_days: [String]
}
let branch: Branch
let subject: [Subject]
}

I donโ€™t what to make more complex above model ๐Ÿ˜…. I have kept everything simple for understanding easily.

Parsing data from JSON response

Our structmodel here Student

I have shown here after making the network request for web API. Directly we are handling network response data through our Codable model. There are no big differences here.

do {
// data
we are getting from network request
let decoder = JSONDecoder()
let response = try decoder.decode(Students.self, from: data)
print(response.subject[0].name) //Output - EMT
} catch { print(error) }

Finally we have done JSON Parsing. This is a very easy process for handling any network response data or JSON object data in your code. So you can handle your UI based on JSON response data. We need to map all required values from response as per requirements. ๐ŸŽ‰


Conclusion

Now finally we got understanding for JSON parsing from web service network request to data handling based on the response. Here I have covered, How to create the model for JSON response ? For managing JSON response properly in your iOS application. I think this is the very easiest way to manage any JSON response with normal model Struct and with the Codable protocol. You can manage it by your self with your own logic as per your requirements. The Codable protocol such a very powerful feature in Foundation library.

I am personally recommending you network SDK for making the network request in Swift. For making an awesome network request inside your application.

Alamofire you can use for making the network request in your application this is an HTTP networking library is very useful and easy to use. If you want to do more advance functionality in your project itโ€™s your choice. ๐Ÿ‘

Now you can create your Model class more easy way with the help of Quicktype. You can generate your Swift code without pain. ๐ŸŽ‰ โœŒ๐Ÿป


Thank You !

I hope you will like this. ๐Ÿ˜Š Thanks for reading. ๐ŸŽ‰

If you having any query regarding this tutorial ? or want to know something more about it. Twitter me: @Anand

Anand Nimje

Written by

I am Swift developer and makes iOS apps