Parse json siêu dễ trong Swift sử dụng Codable

Xin chào các nếu là một developer không sớm thì muộn bạn sẽ gặp phải parse json, bài viết này mình xin hướng dẫn mọi người cách parse json bằng Codable nhé

Codable trong Swift 4

Trong swift 4, Apple đã giới thiệu 1 cách thức mới để mã hoá và giải mã hoá Encodable - dùng cho mã hóa Decodable - dùng cho giải mã Codable - dùng cho cả mã hóa và giải mã Chúng hỗ trợ cả class struct và enum

Encodable Protocol

Một kiểu có thể mã hóa bản thân nó thành một dạng dữ liệu để có thể sử dụng bên ngoài (JSON, plist,…). Nó được sử dụng bởi các types có thể được mã hóa. Nó chứa một phương thức duy nhất:

encode(to:) - Mã hóa giá trị này vào bộ mã hóa đã cho.

Decodable Protocol

Một loại có thể giải mã hoá bản thân nó thành dữ liệu bên ngoài thành đối tượng được sử dụng trong ứng dụng. Nó được sử dụng bởi loại có thể được giải mã Nó cũng chứ một phương thức duy nhất :

init(from:) — Khởi tạo một đối tượng bằng cách giải mã dữ liệu từ bộ giải mã đã cho

Bắt đầu code nhé

Đầu tiên mọi người có thể xem link json ở đây dung là 1 cái parameter mà mình để thôi các bạn có thể để bất cứ tên gì mà các bạn muốn miễn là có data

Ví dụ

Mình có một đoạn json như sau


{
"total_count": 4679,
"incomplete_results": false,
    "items": [
    {
    "login": "dung",
    "id": 384206,
    "node_id": "MDQ6VXNlcjM4NDIwNg==",
    "avatar_url": "https://avatars3.githubusercontent.com/u/384206?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/dung",
    "html_url": "https://github.com/dung",
    "followers_url": "https://api.github.com/users/dung/followers",
    "following_url": "https://api.github.com/users/dung/following{/other_user}",
    "gists_url": "https://api.github.com/users/dung/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/dung/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/dung/subscriptions",
    "organizations_url": "https://api.github.com/users/dung/orgs",
    "repos_url": "https://api.github.com/users/dung/repos",
    "events_url": "https://api.github.com/users/dung/events{/privacy}",
    "received_events_url": "https://api.github.com/users/dung/received_events",
    "type": "User",
    "site_admin": false,
    "score": 145.70857
    },
}


Bước 1 import thư viện

Đầu tiên chúng ta cần import thư viện thông qua cocopods

pod 'Alamofire', '~> 5.0.0-rc.3'

Bước 2 Tạo Model

Chúng ta sẽ tạo 1 file model có tên là User kế thừa từ Codable


import Foundation

struct UserRequest:Codable{
    
    let total_count:Int = 0
    let incomplete_results:Bool
    let items:[User]
}

struct User:Codable{
    let login:String
    let id:Int
    let node_id:String
    let avatar_url:String
 

👉🏼Lưu ý các properties trong Model phải trùng khớp với các key value trong JSON data thì mới parse được json nhé, trong trường hợp mà tên biến trong Model mà không trùng với key value trong Json data chúng ta có thể dùng

enum CodingKeys: String, CodingKey {
    case totalcount = "total_count"
}

Bước 3 parse json

👉🏼 Tiếp theo chúng ta tạp 1 file có tên là DataService trong file này chúng ta sẽ viết 1 class, trong class có chứa 1 closure


import Foundation
import Alamofire
class Dataservice {
    static let intance = Dataservice()
    func fetchData(keyword:String, completion:@escaping(_ user:UserRequest?)->())  {
        AF.request("https://api.github.com/search/users?q=\(keyword)").responseJSON { (response) in
            
            if let error = response.error{
                debugPrint(error.localizedDescription)
                completion(nil)
            }
            
            guard let data = response.data else {return completion(nil)}
            let jsonDecoder = JSONDecoder()
            
            do {
                let person = try jsonDecoder.decode(UserRequest.self, from: data)
                completion(person)
            } catch {
                debugPrint(error.localizedDescription)
                completion(nil)
            }
        }
        
    }
    
    
}

Đoạn code trên làm gì

👉🏼 Ở đây chúng ta dùng thư viện Alamofire như mình đã nói ở trên, vì ở đây chỉ là phương thức get nên chỉ cần dùng AF.request(url) là đủ


AF.request("https://api.github.com/search/users?q=\(keyword)").responseJSON { (response) in


👉🏼 Ở đây chúng ta sử dụng JSONEncoder để chuyển từ kiểu Codable sang data


    let person = try jsonDecoder.decode(UserRequest.self, from: data)

Tiếp theo chúng ta sẽ tạo một file cell để hiển thị thông tin lên Tabel có tên là DasboardCell trong file này chúng ta muốn hiển thị ảnh cũng như tên



import UIKit

    class DasboardCell: UITableViewCell {

        @IBOutlet weak var avatarImageView: UIImageView!
        @IBOutlet weak var usernameLabel: UILabel!
        
        override func awakeFromNib() {
            super.awakeFromNib()
        }
        
        func configureCell(user:User)  {
            DispatchQueue.main.async {
                
                guard let url = URL(string: user.avatar_url) else { return }
                guard let data = try? Data(contentsOf: url) else {return}
                self.avatarImageView.image = UIImage(data: data)
                self.usernameLabel.text = user.login
                
            }
          
        }

        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)

            // Configure the view for the selected state
        }
        
    }

Trong file ViewController chúng ta sẽ hiển thị dữ liệu lên 1 Tableview


//
//  ViewController.swift
//  TestDesignPattern
//
//  Created by Apple on 10/22/19.
//  Copyright © 2019 Apple. All rights reserved.
//

import UIKit


class ViewController: UIViewController {
    
    @IBOutlet weak var userTableView: UITableView!
    var userModel:[User] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        userTableView.register(UINib(nibName: "DasboardCell", bundle: nil), forCellReuseIdentifier: "DasboardCell")

        userTableView.delegate = self
        userTableView.dataSource = self
        Dataservice.intance.fetchData(keyword: "b") { (users) in
            self.userModel = users!.items
            self.userTableView.reloadData()
        }
    
    }
}
extension ViewController:UITableViewDelegate,UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return userModel.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "DasboardCell") as? DasboardCell else   {
    
            return DasboardCell()
        }
        let user = userModel[indexPath.row]
        cell.configureCell(user: user)
        
        
        return cell
        
    }
    
    
}
    


Đoạn code trên làm gì

Ở đây như mình đã nói ở trên bạn có thể truyền vào 1 parameter bất kỳ miễn là có data nhé


Dataservice.intance.fetchData(keyword: "b") { (users) in
           
}

Ok bây giờ chúng ta bấm run để xem kết quả của chúng ta nào

Tổng Kết

Mình vừa hướng dẫn các bạn cách bạn json sử dụng codable bài viết này có thể còn nhiều thiếu sót mong các cao nhân góp ý giúp em, để em có thể cải thiện bài viết sau hơn, mọi thông tin góp ý xin gửi về phamtrungkiendev@gmail.com

Bài viết tham khảo nguồn

Sundell

Apple

Written on January 15, 2020