Parsing JSON in Swift 4 using Decodable Protocol. Parsing a complicate JSON is difficult because of redoing whole process again and again. In swift 4 it's not like swift 2,3, parsing became super easy and fast by just using single line of code. In this tutorial we are diving into Decodable protocol for JSON Parsing.
In this article we will discuss about struct. Structs are very helpful for storing heterogeneous data unlike Array. For example in struct we can store Int, String etc
Creating a simple Struct. Write the following struct next to 'import UIKit'.
Cool, we created structure . Then how to use these Struct? Let write code for testing. Inside viewDidLoad() method write the following code.
Build and Run, See the logs in console. Log should like following image.
First thing we need sample JSON for parsing. So we need sample url for that. This is our sample url :
https://gist.githubusercontent.com/iosRevisited/bf28f444c262591b1807949ff40a2222/raw/695b2de9bc364762377d64595bf2b25a8de69786/sample.json
Now how to get data from that url?
Here we go with simple code using URLSession with completion handler. Here is code for getting data from url. Delete all code inside viewDidLoad() method and replace with following code.
Now Build and Run we will see data as following.
Now store the data in struct. So need to initialize with dictionary. Replace old Struct with new Struct.
Then replace 'print(json)' line with following code.
Build and Run we will see the name in the console.
Up to now what we did is old methods we used in Swift 2/3/Objective-C.
Now step into the new method introduced by apple in iOS 11 is Decodable Protocol. Remove init method in structure and provide Decodable Protocol to struct.
Replace structure with new struct with protocol.
Replace the code inside do { } block with following code.
Now Build and Run we will get the name as before but we never initialized the structure as before.
Now let see this JSON:
This is a bit complex than before. No worries, using swift 4 this became super easy. That JSON contains array of tutorials.
Change url to https://gist.githubusercontent.com/iosRevisited/7e6cd23e2a267a2503698411a834fe6c/raw/890f5842181369b83c820b4a6702b42776a9aabf/tutorials.json
Replace old url with new url. Then it looks like this.
Then inside do block change decode code to array like this [Tutorial]. Replace do block with following code.
Build and Run, Array of data appears like this:
Great, array of dictionaries also parsed using decodable protocol.
Now we will parse the following data from url - https://gist.githubusercontent.com/iosRevisited/65fff3a78a684909a7b64761799a02d3/raw/0850d72db8315ff25d2a24219d6592fd404deb35/Complex.json
This structure is totally different from our struct model. We need to create one more model as following.
Here we reused Tutorial Struct.
Now change urString. It looks like following.
Then replace code inside do block.
Build and Run , we will see following as output in console.
Cool, we parsed data easily in a efficient way using Decodable Protocol.
Getting Started:
Create new project -> open Xcode -> File -> New -> Project -> Single View App, then tap next button. Type product name as 'JSONParseSwift4' then tap next and select the folder to save project.In this article we will discuss about struct. Structs are very helpful for storing heterogeneous data unlike Array. For example in struct we can store Int, String etc
Creating a simple Struct. Write the following struct next to 'import UIKit'.
struct Tutorials {
let id : Int
let name : String
let link : String
let imageUrl : String
}
let myTutorial = Tutorials(id: 1, name: "my tutorial", link: "some link", imageUrl: "some image")
print(myTutorial)
First thing we need sample JSON for parsing. So we need sample url for that. This is our sample url :
https://gist.githubusercontent.com/iosRevisited/bf28f444c262591b1807949ff40a2222/raw/695b2de9bc364762377d64595bf2b25a8de69786/sample.json
Now how to get data from that url?
Here we go with simple code using URLSession with completion handler. Here is code for getting data from url. Delete all code inside viewDidLoad() method and replace with following code.
let urlString = "https://gist.githubusercontent.com/iosRevisited/bf28f444c262591b1807949ff40a2222/raw/695b2de9bc364762377d64595bf2b25a8de69786/sample.json"
guard let url = URL(string: urlString) else {
return
}
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
// Old School method for parsing Swift 2/3/Objective-C
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
print(json)
} catch let jsonErr {
print("error in parsing",jsonErr)
}
}.resume()
Now store the data in struct. So need to initialize with dictionary. Replace old Struct with new Struct.
struct Tutorials {
let id : Int
let name : String
let link : String
let imageUrl : String
init(json:[String: Any]) {
id = json["id"] as? Int ?? 0
name = json["name"] as? String ?? ""
link = json["link"] as? String ?? ""
imageUrl = json["imageUrl"] as? String ?? ""
}
}
let tutorial = Tutorials(json: json)
print(tutorial.name)
Up to now what we did is old methods we used in Swift 2/3/Objective-C.
Now step into the new method introduced by apple in iOS 11 is Decodable Protocol. Remove init method in structure and provide Decodable Protocol to struct.
Replace structure with new struct with protocol.
struct Tutorial: Decodable {
let id : Int
let name : String
let link : String
let imageUrl : String
}
let tutorial = try JSONDecoder().decode(Tutorial.self, from: data)
print(tutorial.name)
Important - we should match the data keys with the structure properties.
Array of Dictionaries :
Now let see this JSON:
[
{
"id": 1,
"name": "Face Detection",
"link": "http://iosrevisited.blogspot.com/2017/08/face-detection-using-vision-framework.html",
"imageUrl": "https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png"
},
{
"id": 2,
"name": "Real Time Object Detection",
"link": "http://iosrevisited.blogspot.com/2017/08/real-time-camera-object-detection-with.html",
"imageUrl": "https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png"
}
]
Change url to https://gist.githubusercontent.com/iosRevisited/7e6cd23e2a267a2503698411a834fe6c/raw/890f5842181369b83c820b4a6702b42776a9aabf/tutorials.json
Replace old url with new url. Then it looks like this.
let urlString = "https://gist.githubusercontent.com/iosRevisited/7e6cd23e2a267a2503698411a834fe6c/raw/890f5842181369b83c820b4a6702b42776a9aabf/tutorials.json"
let tutorials = try JSONDecoder().decode([Tutorial].self, from: data)
print("\(tutorials)")
Great, array of dictionaries also parsed using decodable protocol.
Complex Data Parsing:
Now we will parse the following data from url - https://gist.githubusercontent.com/iosRevisited/65fff3a78a684909a7b64761799a02d3/raw/0850d72db8315ff25d2a24219d6592fd404deb35/Complex.json
{
"name": "iOS Revisited",
"description": "Blog about,Objective c language and Swift language programming questions, Tutorials, Bugs solving ....",
"tutorials": [
{
"id": 1,
"name": "Face Detection",
"link": "http://iosrevisited.blogspot.com/2017/08/face-detection-using-vision-framework.html",
"imageUrl": "https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png"
},
{
"id": 2,
"name": "Real Time Object Detection",
"link": "http://iosrevisited.blogspot.com/2017/08/real-time-camera-object-detection-with.html",
"imageUrl": "https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png"
}
]
}
struct siteDescription: Decodable {
let name: String
let description: String
let tutorials: [Tutorial]
}
Now change urString. It looks like following.
let urlString = "https://gist.githubusercontent.com/iosRevisited/65fff3a78a684909a7b64761799a02d3/raw/0850d72db8315ff25d2a24219d6592fd404deb35/Complex.json"
let siteData = try JSONDecoder().decode(SiteDescription.self, from: data)
print("\nname = \(siteData.name)")
print("\ndescription = \(siteData.description)")
print("\ntutorials = \(siteData.tutorials)")
Build and Run , we will see following as output in console.
Cool, we parsed data easily in a efficient way using Decodable Protocol.
import UIKit
ReplyDeletestruct detail : Decodable {
let id: Int
let name: String
let tel: String
let address: String
let longitude: Float
let latitude: Float
}
struct Scenics : Decodable {
let result: String
let message: String
let recordset: [detail]
}
class ViewController: UIViewController {
var countries = [Country]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let jsonURL = "http://research.cumi.co/scenics.php"
let url = URL(string: jsonURL)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard let data = data else {return}
do {
let scenics = try JSONDecoder().decode(Scenics.self, from: data)
print(scenics.message)
}
catch {
print("error")
}
}.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Hi, above is my code.
But always error at runtime.
how to fix it?
Thanks Advances