Content posted here with the permission of the author Shirish Bankar, who is currently employed at Josh Software. Original post available here
We have always spent hefty amount of time to parse and format a JSON response to our views and same amount of time again to collect data from there and create a JSON key by key to post to server. It was the traditional way until Apple gave us JSON Codable protocol at WWDC with Swift 4. An elegant way to parse and create JSON to and from models equivalent to the JSON hierarchy.
Swift Codable protocol has offered following things to us :
- Using Codable, we can model JSONObject or PropertyList file into equivalent Struct or Classes by writing very few lines of code. We don’t have to write the constructor for the properties in the objects. It’s all handed by Codable. We just need to extend our model to conform to the Codable, Decodable or Encodable protocol.
- Mismatch between the strong data types of Swift and loose data types of JSON has been internally handled by Swift compiler. We can now handle Swift Data types like Date, URL, Float etc
- Complex JSON can be modelled easily using Nesting Structs for readability.
- Parsing actual JSON become one-liner using JSONDecoder
For instance we’ll use below JSON :
{ “username”: “shirish@joshsoftware.com”, “id”: 628593, “profile_image”: “https: //josh.intranet.com/shirish21790.jpeg", “designation”: “senior ios developer”, “name”: “Shirish Bankar”, “company”:” [“Deskera”, “MangoApps”, “Josh software”]”, “personal_info” : { “dob”:”21–07–1990", ”blood_group”: ”bpositive”, ”marital_status”: ”married”, ”contact”: ”8669005821" } }
Now to parse this JSON we’ll create following struct.
struct EmployeeInfo { let username: String? let designation: String? let id: Int? let profile_image: URL? let company: [String]? let personal_info : PersonalInfo? }
Here profile_image is of URL type in our struct and in JSON its a string. Now conforming to Codable protocol will take care of this type mismatch. Here we also have a type PersonalInfo which will become another struct to create a hierarchy and conforming it to Codable will parse data into it too along with EmployeeInfo. Also, notice few constants are declared as camel case which is not Swift standard convention. To take care of camel case we declare CodingKeys enum and tell to use snake case for Swift constant and camel case for JSON. Our final struct will be like :
struct EmployeeInfo: Codable { let username: String? let designation: String? let id: Int? let profileImageUrl: URL? let company: [String]? let personal_info : PersonalInfo? private enum CodingKeys: String, CodingKey { case username case designation case id case profileImageUrl = "profile_image” case avatarUrl = "avatar_url” case company case personalInfo = "personal_info" } }
Parsing JSON with Codable
guard let apiUrl = URL(string: "https://api.getMyJSON/shirishInfo?") else { return } URLSession.shared.dataTask(with: apiUrl) { (data, response, error) in guard let data = data else{return} do { let decoder = JSONDecoder() let myData = try decoder.decode(EmployeeInfo.self, from: data) print(myData.username) } catch let err { print(“Err”, err) } }.resume()
We have parsed our JSON data (supposedly) received from the api url. We can access all properties using myData variable.
Now the reverse procedure :-
Creating JSON from your struct :
let encoder = JSONEncoder()encoder.outputFormatting = .prettyPrintedlet data = try encoder.encode(myData)print(String(data: data, encoding: .utf8)!) //** This is our json **//
Thats it we can use JSONEncoder to create JSON to be sent to server this easily . So this is the real magic behind Codable .