美文网首页SwiftSwift
Swift 字典转模型(KakaJSON) ---1.基本用法

Swift 字典转模型(KakaJSON) ---1.基本用法

作者: 浅宇落 | 来源:发表于2019-11-14 10:28 被阅读0次

    在iOS开发中,后台返回的数据大多是JSON格式,对应地会被网络框架层解析成Swift中的Dictionary、Array。由于数据类型的复杂、字段的繁多,直接使用Dictionary、Array会比较麻烦,比如items[0]["user"]["name"]这样的使用方式,非常不友善,而且没有智能语法提示。所以很多时候会考虑将JSON转换成Model之后再进行操作,会友善很多,比如items[0].user.name。

    1.最简单的Model

    // ① 让模型类型遵守`Convertible`协议
    struct Cat: Convertible {
      var name: String = ""
      var weight: Double = 0.0
    }
            
    // json也可以是NSDictionary、NSMutableDictionary类型
    let json: [String: Any] = [
      "name" : "Miaomiao",
      "weight" : 6.66
    ]
            
    // ② 直接调用json的model方法,传入模型类型,返回模型实例
    let cat = json.kj.model(Cat.self)
    //let cat = model(from: json, Cat.self)
            
    print("name:\(cat.name),  weight:\(cat.weight)")
    // name:Miaomiao,  weight:6.66
    

    2.Class类型

    class Cat: Convertible {
      var name: String = ""
      var weight: Double = 0.0
                
      // 由于Swift初始化机制的原因,`Convertible`协议强制要求实现init初始化器
      // 这样框架内部才可以完整初始化一个实例
      required init() {}
    }
            
    let json: [String: Any] = [
      "name" : "老斑",
      "weight" : 6.66
    ]
            
    let cat = json.kj.model(Cat.self)
    print("name:\(cat.name),  weight:\(cat.weight)")
    // name:老斑,  weight:6.66
    
    
    // 继承自NSObject的类也是一样的用法
    class Person: NSObject, Convertible {
        var name: String = ""
        var age: Int = 0
        
        // 由于NSObject内部已经有init,因此Person算是重载init,需再加上`override`
        required override init() {}
    }
    
    let json: [String: Any] = [
        "name" : "李连杰",
        "age" : 67
    ]
    
    let person = json.kj.model(Person.self)
    print("name:\(person.name),  age:\(person.age)")
    // name:李连杰,  age:67
    
    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
        }
    }
    

    3.继承

    class Person: Convertible {
        var name: String = ""
        var age: Int = 0
        
        // 由于NSObject内部已经有init,因此Person算是重载init,需再加上`override`
        required init() {}
    }
    class Student: Person {
        var score: Int = 0
        var no: String = ""
    }
    
    let json: [String: Any] = [
        "name": "jack",
        "age": 18,
        "score": 98,
        "no": "9527"
    ]
    
    let student = json.kj.model(Student.self)
    print("name:\(student.name),  age:\(student.age),  score:\(student.score),  no:\(student.no)")
    // name:jack,  age:18,  score:98,  no:9527
    

    4.let属性

    struct Cat: Convertible {
        // 测试表明:在真机release模式下,对数字类型的let限制比较严格
        // 值虽然修改成功了(可以打印Cat结构体发现weight已经改掉了),但get出来还是0.0
        // 所以建议使用`private(set) var`取代`let`
        private(set) var weight: Double = 0.0
        let name: String = ""
    }
            
    let json: [String: Any] = [
        "name" : "Miaomiao",
        "weight" : 6.66
    ]
    
    let cat = json.kj.model(Cat.self)
    print("name:\(cat.name),  weight:\(cat.weight)")
    // name:Miaomiao,  weight:6.66
    

    5. JSONString

    struct Cat: Convertible {
        var weight: Double = 0.0
        var name: String = ""
    }
    
    // jsonString也可以是NSString、NSMutableString类型     
    let jsonString = """
    {
        "name": "Miaomiao",
        "weight": 6.66
    }
    """
    
    let cat = jsonString.kj.model(Cat.self)
    guard let cat1 = cat else { // guard let 守护
        return
    }
    print("name:\(cat1.name),  weight:\(cat1.weight)")
    // name:Miaomiao,  weight:6.66
    

    6. JSONData

    struct Cat: Convertible {
        var weight: Double = 0.0
        var name: String = ""
    }
    
    // jsonData也可以是NSData、NSMutableData类型     
    let jsonData = """
    {
        "name": "Miaomiao",
        "weight": 6.66
    }
    """.data(using: .utf8)!
    
    let cat = jsonData.kj.model(Cat.self)
    guard let cat1 = cat else {
        return
    }
    print("name:\(cat1.name),  weight:\(cat1.weight)")
    // name:Miaomiao,  weight:6.66
    

    7.Model嵌套1

    // 让需要进行转换的模型都遵守`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.kj.model(Person.self)
            
    guard let car = person.car,
        let books = person.books,
        let dogs = person.dogs else {
        return
    }
    
    print("name:\(person.name),  car:\(car)")
    
    for book: Book in books {
        print("book:\(book)")
    }
    for (key, value) in dogs {
        print("key:\(key) value:\(value)")
    }
    /*
    name:Jack,  car:Car(name: "BMW7", price: 105.5)
    book:Book(name: "Fast C++", price: 666.6)
    book:Book(name: "Data Structure And Algorithm", price: 1666.6)
    key:dog0 value:Dog(name: "Larry", age: 5)
    key:dog1 value:Dog(name: "ErHa", age: 2)
    */
    

    8.Model嵌套2

    struct Car: Convertible {
        var name: String = ""
        var price: Double = 0.0
    }
    
    class Dog: Convertible {
        var name: String = ""
        var age: Int = 0
        required init() {}
        init(name: String, age: Int) {
            self.name = name
            self.age = age
        }
    }
    
    struct Person: Convertible {
        var name: String = ""
        // 如果你的模型有默认值,KakaJSON内部不会再创建新的模型
        // 会直接重复利用你创建的模型,节省内存分配和初始化的开销
        var car: Car = Car(name: "Bently", price: 106.5)
        var dog: Dog = Dog(name: "Larry", age: 5)
    }
            
    let json: [String: Any] = [
        "name": "Jake",
        "car": ["price": 305.6],
        "dog": ["name": "Wangwang"]
    ]
    
    let person = json.kj.model(Person.self)
    print("name:\(person.name),  car:\(person.car)")
    print("dog: ----> name:\(person.dog.name)  age:\(person.dog.age)")
    /*
    name:Jake,  car:Car(name: "Bently", price: 305.6)
    dog: ----> name:Wangwang  age:5
    */
    

    9.泛型

    struct NetRespones<Element>: Convertible {
        let data: Element? = nil
        let msg: String = ""
        private(set) var code: Int = 0
        
    }
    
    struct User: Convertible {
        let id: String = ""
        let nickName: String = ""
    }
    
    struct Goods: Convertible {
        private(set) var price: CGFloat = 0.0
        let name: String = ""
    }
    
    let json1 = """
        {
        "data": {"nickName": "KaKa", "id": 213234234},
        "msg": "Success",
        "code" : 200
        }
        """
    let response = json1.kj.model(NetRespones<User>.self)
    
    guard let response1 = response  else {
        return
    }
    print("response: msg: \(response1.msg)  code:\(response1.code)  data:\(response1.data ?? User())")
    // response: msg: Success  code:200  data:User(id: "213234234", nickName: "KaKa")
    

    10.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.kj.modelArray(Car.self)
    
    for car: Car in cars {
        print("car: \(car)")
    }
    print("----------------------------")
    
    for (index, value) in cars.enumerated() {
        print("index: \(index)   value: \(value)")
    }
    /*
    car: Car(name: "Benz", price: 98.6)
    car: Car(name: "Bently", price: 305.7)
    car: Car(name: "Audi", price: 64.7)
    ----------------------------
    index: 0   value: Car(name: "Benz", price: 98.6)
    index: 1   value: Car(name: "Bently", price: 305.7)
    index: 2   value: Car(name: "Audi", price: 64.7)
    */
    

    11. Convert

    // 如果你想把JSON数据转换到原本已经创建好的模型实例上,可以使用convert方法
    
    struct Cat: Convertible {
        var name: String = ""
        var weight: Double = 0.0
    }
    
    let json: [String: Any] = [
        "name": "Miaomiao",
        "weight": 6.66
    ]
    
    var cat = Cat()
    // .kj_m是.kj的mutable版本,牵扯到修改实例本身都是.kj_m开头
    cat.kj_m.convert(from: json)
    print("name: \(cat.name)   weight\(cat.weight)")
    // name: Miaomiao   weight6.66
    

    12. 监听

    // 有时候可能想在JSON转模型之前、之后做一些额外的操作
    // KakaJSON会在JSON转模型之前调用模型的kj_willConvertToModel方法
    // KakaJSON会在JSON转模型之后调用模型的kj_didConvertToModel方法
    
    struct Car: Convertible {
        var name: String = ""
        var age: Int = 0
        
        func kj_willConvertToModel(from json: [String : Any]) {
            print("Car - kj_willConvertToModel")
        }
        
        mutating func kj_didConvertToModel(from json: [String : Any]) {
            print("Car - kj_didConvertToModel")
        }
    }
    
    let json: [String: Any] = [
        "name": "Benz",
        "age": 100
    ]
    
    var car = json.kj.model(Car.self)
    print("name: \(car.name)   age: \(car.age)")
    /*
    Car - kj_willConvertToModel
    Car - kj_didConvertToModel
    name: Benz   age: 100
    */
    
    /*************************************************************/
    
    // 同样也支持类
    class Person: Convertible {
        var name: String = ""
        var age: Int = 0
        required init() {}
        
        func kj_willConvertToModel(from json: [String: Any]) {
            print("Person - kj_willConvertToModel")
        }
        
        func kj_didConvertToModel(from json: [String: Any]) {
            print("Person - kj_didConvertToModel")
        }
    }
    
    class Student: Person {
        var score: Int = 0
        
        override func kj_willConvertToModel(from json: [String : Any]) {
            // 如果有必要的话,可以调用super的实现
            super.kj_willConvertToModel(from: json)
            
            print("Student - kj_willConvertToModel")
        }
        
        override func kj_didConvertToModel(from json: [String: Any]) {
            // 如果有必要的话,可以调用super的实现
            super.kj_didConvertToModel(from: json)
            
            print("Student - kj_didConvertToModel")
        }
    }
    
    let json: [String: Any] = [
        "name" : "jack",
        "age" : 10,
        "score" : 100
    ]
    
    let student = json.kj.model(Student.self)
    print("name:\(student.name),  age:\(student.age)  score:\(student.score)")
    /*
    Person - kj_willConvertToModel
    Student - kj_willConvertToModel
    Person - kj_didConvertToModel
    Student - kj_didConvertToModel
    name:jack,  age:10  score:100
    */
    

    Swift 字典转模型(KakaJSON) ---2.数据类型
    Swift 字典转模型(KakaJSON) ---3.key处理
    Swift 字典转模型(KakaJSON) ---4.动态模型
    Swift KakaJSON 05.---模型转字典
    Swift KakaJSON 06.---Coding/归档/解档

    相关文章

      网友评论

        本文标题:Swift 字典转模型(KakaJSON) ---1.基本用法

        本文链接:https://www.haomeiwen.com/subject/fqqkictx.html