Recently, JSON has become most widely used format to transfer data all over the internet. In the world of iOS development, it’s very common for the developer to work with JSON data in Swift and use it for building iOS apps. There are some cool libraries like SwiftyJSON already available to work with JSON data in Swift and those libraries become popular because developers don’t need to deal with unreadable mess with
JSONSerialization to parse JSON. Fortunately, Swift 4 has introduced amazing Codable protocol as part of Foundation framework and JSON parsing became a single or couple of lines of code. This is fully supported solution by Apple that can be easily adopted. It provides customisation to encode and decode complex scenarios with pain.
In this article, we will see how to parse JSON using Swift 4 Codable by building Github Information app.
Swift Codable
At WWDC 2017, Apple has introduced the new feature in Swift to parse JSON without any pain using Swift Codable protocol. There is talk available to watch on Whats New in Foundation, you can watch about this new featured from 23 min onwards. Basically, this protocol has the combination of Encodable and Decodable protocol that can be used to work with JSON data in both directions. In summary, 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 lose 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
There are many articles already written on this topic to cover end to end introduction of Codable protocol. But in this brief article, we will use GitHub API and build a sample App to demonstrate this feature in brief.
GitHub User Info App
We will use very famous GitHub API to demonstrate this feature. We will build a simple app that takes GitHub username and shows some information when we tap on “Show” button.
There is an API to display public information of GitHub Users e.g I can find the details of my GitHub account by using this API endpoint
1 |
https://api.github.com/users/shashikant86 |
This will return the information in JSON format which looks like this at the moment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
{ "login": "Shashikant86", "id": 683799, "avatar_url": "https://avatars0.githubusercontent.com/u/683799?v=4", "gravatar_id": "", "url": "https://api.github.com/users/Shashikant86", "html_url": "https://github.com/Shashikant86", "followers_url": "https://api.github.com/users/Shashikant86/followers", "following_url": "https://api.github.com/users/Shashikant86/following{/other_user}", "gists_url": "https://api.github.com/users/Shashikant86/gists{/gist_id}", "starred_url": "https://api.github.com/users/Shashikant86/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/Shashikant86/subscriptions", "organizations_url": "https://api.github.com/users/Shashikant86/orgs", "repos_url": "https://api.github.com/users/Shashikant86/repos", "events_url": "https://api.github.com/users/Shashikant86/events{/privacy}", "received_events_url": "https://api.github.com/users/Shashikant86/received_events", "type": "User", "site_admin": false, "name": "Shashikant", "company": "@AOL, @BBC, @PhotoBox", "blog": "http://shashikantjagtap.net", "location": "London", "email": null, "hireable": null, "bio": "Author of BDDfire & XCFit. DevOps Automation iOS Swift PHP Ruby Development. CI&CD[Jenkins, Docker, AWS, Xcode Server] BDD[Cucumber Behat Cucumberish, Fitnesse]", "public_repos": 112, "public_gists": 1, "followers": 108, "following": 52, "created_at": "2011-03-22T12:39:11Z", "updated_at": "2017-10-05T14:32:54Z" } |
This is actually a lot of information but for the demo, we will only use following properties.
- name
- avatar_url
- location
- followers
- public_repos
Now that, we have our endpoints. Let’s create a single View iOS Application in Xcode. We could use MVC, MVVM or similar pattern but we will do everything in the ViewController.Swift for this demo. We can easily model this information using simple Swift Struct like this
1 2 3 4 5 6 7 |
struct MyGitHub { let name: String? let location: String? let followers: Int? let avatar_url: URL? let public_repo: Int? } |
Probably, I can go ahead and write ad constructor for each property and so on. However, I will stop myself at this stage as I already spotted the problems
- The constant avatar_url is of type URL but in JSON it’s String.
- Also, notice that constant is declared as camel case which is not Swift standard convention.
Fortunately, Codable has an answer to both problems.
- We have to make our Struct to conform to Codable protocol which will take care of Data Type Mismatch. The Swift compiler will take care of it under the hood. We don’t need to write constructor as well.
- In order to solve camel case problem, we can declare Coding Keys enum and tell to use snake case for Swift constant and camel case for JSON.
The resulting Struct will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
struct MyGitHub: Codable { let name: String? let location: String? let followers: Int? let avatarUrl: URL? let repos: Int? private enum CodingKeys: String, CodingKey { case name case location case followers case repos = "public_repos" case avatarUrl = "avatar_url" } } |
Now that, we have achieved out snake casing for Swift and we also have Swift types in our model by conforming to Codable protocol.
Parsing JSON with JSONDecoder
Now we have our JSON endpoints and model based on the JSON, let’s see how easy it is to parse this JSON. First, we will make the request to the endpoint and grab the JSON and with single line of code we will parse the JSON using JSONDecoder
1 2 3 4 5 6 7 8 9 10 11 12 13 |
guard let gitUrl = URL(string: "https://api.github.com/users/shashikant86") else { return } URLSession.shared.dataTask(with: gitUrl) { (data, response , error) in guard let data = data else { return } do { let decoder = JSONDecoder() let gitData = try decoder.decode(MyGitHub.self, from: data) print(gitData.name) } catch let err { print("Err", err) } }.resume() |
That’s it! We have parsed out JSON with single or couple of lines of code. We can now print all the properties using gitData object.
Preparing UI for APP
Now that, we have parsed out JSON and we can access all the properties that needed for our app. Let’s build some UI for the app to ask users to enter Github username and press show button. We will also put some label to display this information in the UI.
Note: I am horrible in designing the UI so my crappy storyboard looks like this
We will then link that UI element to ViewController to display specific information.
Source code
The source code for this demo app is available on GitHub
Just clone the repo and play with code
1 2 3 |
$ git clone git@github.com:Shashikant86/Decodable-Swift4.git $ cd Decodable-Swift4 $ open Decodable.xcodeproj |
Have Fun and enjoy Codable Protocol. Our App will look like this at the end.
Conclusion
Using Swift 4 and Codable protocol, it became very easy to parse any JSON with any complexity and use them in the iOS apps. Thanks to the Foundation framework team to provide such a great feature embedded in the Swift. It’s your decision to convert all your models to use Codable protocol and probably retire third-party framework that has been used to parse JSON from your iOS apps.