1. 程式人生 > >【KakaJSON手冊】01_JSON轉Model_01_基本用法

【KakaJSON手冊】01_JSON轉Model_01_基本用法

在iOS開發中,後臺返回的資料大多是JSON格式,對應地會被網路框架層解析成Swift中的Dictionary、Array。由於資料型別的複雜、欄位的繁多,直接使用Dictionary、Array會比較麻煩,比如items[0]["user"]["name"]這樣的使用方式,非常不友善,而且沒有智慧語法提示。所以很多時候會考慮將JSON轉換成Model之後再進行操作,會友善很多,比如items[0].user.name

  • Swift內建了一套Codable機制,可以用於JSON轉Model。對於一些簡單的模型結構,還是挺好用,但一旦牽扯到複雜的模型結構、一些個性化的需求(比如KeyMapping、型別不匹配時的轉換處理、自定義解析規則等),Codable就無法友善地完成任務了。
  • 為了解決上述問題,我編寫了一套純Swift實現的JSON與Model互相轉換的框架:KakaJSON,本人非常喜歡龍珠,框架取名自Kaka Rotto(卡卡羅特,孫悟空)。基於之前編寫過OC版本的JSON\Model轉換框架MJExtension的經驗,繞過了很多坑,編寫過程也比較順利。對外提供了一些友善易用、可擴充套件的介面,內建了Metedata快取等機制,加快轉換速度。
  • 本教程是為了讓大家能夠快速上手KakaJSON的使用,挖掘它內部的各種功能,發揮它的最大威力。未來也可以會推出一些原始碼分析的文章。

最簡單的Model

import KakaJSON

// ① 讓模型型別遵守`Convertible`協議
struct Cat: Convertible {
    var weight: Double = 0.0
    var name: String = ""
}

let json: [String: Any] = [
    "weight": "Miaomiao",
    "name": 6.66
]

// ② 直接呼叫json的model方法,傳入模型型別,返回模型例項
let cat = json.kk.model(Cat.self)
print(cat?.name) // Miaomiao
print(cat?.weight) // 6.66

// 或者也可以呼叫一個全域性函式來完成字典轉模型
let cat2 = model(from: json, Cat.self)

Any.Type

// 有時型別可能是個變數,比如
var type: Any.Type = Cat.self

// 呼叫帶有anyType引數的方法即可
// 由於傳入的型別是Any.Type,所以返回值型別是Any,到時根據需求強制轉換成自己想要的型別
let cat = json.kk.model(anyType: type) as? Cat

// 或者呼叫全域性函式
let cat2 = model(from: json, anyType: type) as? Cat

Class型別

class Cat: Convertible {
    var weight: Double = 0.0
    var name: String = ""
    // 由於Swift初始化機制的原因,`Convertible`協議強制要求實現init初始化器
    // 這樣框架內部才可以完整初始化一個例項
    required init() {}
}
let json = ...
let cat = json.kk.model(Cat.self)

struct Dog: Convertible {
    var weight: Double = 0.0
    var name: String = ""
    // 由於編譯器自動幫結構體型別生成了一個init初始化器
    // 所以不需要自己再實現init初始化器
}

struct Pig: Convertible {
    var weight: Double
    var name: String
    // 如果沒有在定義屬性的同時指定初始值,編譯器是不會為結構體生成init初始化器的
    // 所以需要自己實現init初始化器
    init() {
        name = ""
        weight = 0.0
    }
}

let屬性

// KakaJSON也支援let屬性
struct Cat: Convertible {
    let weight: Double = 0.0
    let name: String = ""
}
let json = ...
let cat = json.kk.model(Cat.self)

JSONString

// jsonString可以是String、NSString、NSMutableString
let jsonString: String = """
{
    "name": "Miaomiao",
    "weight": 6.66
}
"""

// 跟JSON的用法是一樣的
let cat = jsonString.kk.model(Cat.self)
let cat2 = model(from: jsonString, Cat.self)
var type: Any.Type = Cat.self
let cat3 = jsonString.kk.model(anyType: type) as? Cat
let cat4 = model(from: jsonString, anyType: type) as? Cat

Model巢狀

// 讓需要進行轉換的模型都遵守`Convertible`協議

struct Book: Convertible {
    var name: String = ""
    var price: Double = 0.0
}

struct Car: Convertible {
    var name: String = ""
    var price: Double = 0.0
}

struct Dog: Convertible {
    var name: String = ""
    var age: Int = 0
}

struct Person: Convertible {
    var name: String = ""
    var car: Car?
    var books: [Book]?
    var dogs: [String: Dog]?
}

let json: [String: Any] = [
    "name": "Jack",
    "car": ["name": "BMW7", "price": 105.5],
    "books": [
        ["name": "Fast C++", "price": 666.6],
        ["name": "Data Structure And Algorithm", "price": 1666.6]
    ],
    "dogs": [
        "dog0": ["name": "Larry", "age": 5],
        "dog1": ["name": "ErHa", "age": 2]
    ]
]

// 就是如此簡單,不用再做額外的操作
let person = json.kk.model(Person.self)
print(person?.car?.name) // BMW7
print(person?.books?[1].name) // Data Structure And Algorithm
print(person?.dogs?["dog0"]?.name) // Larry

Model陣列

struct Car: Convertible {
    var name: String = ""
    var price: Double = 0.0
}

// json陣列可以是Array<[String: Any]>、NSArray、NSMutableArray
let json: [[String: Any]] = [
    ["name": "Benz", "price": 98.6],
    ["name": "Bently", "price": 305.7],
    ["name": "Audi", "price": 64.7]
]

// 呼叫json陣列的modelArray方法即可
let cars = json.kk.modelArray(Car.self)
print(cars?[1].name) // Bently

// 同樣的還有其他方式
let cars2 = modelArray(from: json, Car.self)
var type: Any.Type = Car.self
let cars3 = json.kk.modelArray(anyType: type) as? [Car]
let cars4 = modelArray(from: json, anyType: Car.self) as? [Car]

// 另外,jsonString轉為Model陣列,也是如此簡單
let jsonString = "...."
let cars5 = jsonString.kk.modelArray(Car.self)
let cars6 = modelArray(from: jsonString, Car.self)
let cars7 = jsonString.kk.modelArray(anyType: type) as? [Car]
let cars8 = modelArray(from: jsonString, anyType: Car.self) as? [Car]