【KakaJSON手冊】05_JSON轉Model_05_動態模型

上一篇文章中提到:有時候服務器返回的某個字段的內容類型多是不肯定的html

  • 當時給出的解決方案是實現kj_modelValue或者kj_didConvertToModel方法,根據實際需求自定義JSON的解析邏輯
  • 若是不肯定的內容是要轉成模型,KakaJSON有更簡單的實現方案

舉例

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

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

struct Pig: Convertible {
    var name: String = ""
    var height: Double = 0.0
}

struct Dog: Convertible {
    var name: String = ""
    var weight: Double = 0.0
}

struct Person: Convertible {
    var name: String = ""
    var pet: Any?

    // 這裏用`NSArray`、`NSMutableArray`也行
    var toys: [Any]?

    // 這裏用`NSDictionary`、`NSMutableDictionary`也行
    var foods: [String: Any]?

    func kj_modelType(from jsonValue: Any?, _ property: Property) -> Convertible.Type? {
        switch property.name {
        case "toys": return Car.self  // `toys`數組存放`Car`模型
        case "foods": return Book.self  // `foods`字典存放`Book`模型
        case "pet":
            if let pet = jsonValue as? [String: Any], let _ = pet["height"] {
                // 若是`pet`屬性的`jsonValue`是個字典,而且有`height`這個key,就轉爲`Pig`模型
                return Pig.self
            }
            // 將`jsonValue`轉爲`Dog`模型賦值給`pet`屬性
            return Dog.self
        default: return nil
        }
    }
}

// 測試數據
let name = "Jack"
let dog = (name: "Wang", weight: 109.5)
let pig = (name: "Keke", height: 1.55)
let books = [
    (name: "Fast C++", price: 666.0),
    (name: "Data Structure And Algorithm", price: 1666.0)
]
let cars = [
    (name: "Benz", price: 100.5),
    (name: "Bently", price: 300.6)
]

// JSON數據
let json: [String: Any] = [
    "name": name,
    "pet": ["name": dog.name, "weight": dog.weight],
    // "pet": ["name": pig.name, "height": pig.height],
    "toys": [
        ["name": cars[0].name, "price": cars[0].price],
        ["name": cars[1].name, "price": cars[1].price]
    ],
    "foods": [
        "food0": ["name": books[0].name, "price": books[0].price],
        "food1": ["name": books[1].name, "price": books[1].price]
    ]
]

let person = json.kj.model(Person.self)
XCTAssert(person.name == name)

if let pet = person.pet as? Dog {
    XCTAssert(pet.name == dog.name)
    XCTAssert(pet.weight == dog.weight)
} else if let pet = person.pet as? Pig {
    XCTAssert(pet.name == pig.name)
    XCTAssert(pet.height == pig.height)
}

let toy0 = person.toys?[0] as? Car
XCTAssert(toy0?.name == cars[0].name)
XCTAssert(toy0?.price == cars[0].price)

let toy1 = person.toys?[1] as? Car
XCTAssert(toy1?.name == cars[1].name)
XCTAssert(toy1?.price == cars[1].price)

let food0 = person.foods?["food0"] as? Book
XCTAssert(food0?.name == books[0].name)
XCTAssert(food0?.price == books[0].price)

let food1 = person.foods?["food1"] as? Book
XCTAssert(food1?.name == books[1].name)
XCTAssert(food1?.price == books[1].price)
相關文章
相關標籤/搜索