因爲JSON格式能表達的數據類型是比較有限的,因此服務器返回的JSON數據有時沒法自動轉換成客戶端想要的數據類型。git
1565480696
,但客戶端想要的是Date
類型Double
類型,但服務器返回的多是字符串類型"6.45"
Bool
類型,但服務器返回的多是"true"
、"1"
、0
NSDecimalNumber
類型,服務器爲了維持精度可能返回字符串"0.1234567890123456789"
struct Student: Convertible { var age1: Int8 = 6 var age2: Int16 = 0 var age3: Int32 = 0 var age4: Int64 = 0 var age5: UInt8 = 0 var age6: UInt16 = 0 var age7: UInt32 = 0 var age8: UInt64 = 0 var age9: UInt = 0 var age10: Int = 0 var age11: Int = 0 } let json: [String: Any] = [ "age1": "suan8fa8", "age2": "6suan8fa8", "age3": "6", "age4": 6.66, "age5": NSNumber(value: 6.66), "age6": Int32(6), "age7": true, "age8": "FALSE", "age9": Decimal(6.66), "age10": NSDecimalNumber(value: 6.66), "age11": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) // 解析失敗,因此使用默認值6 XCTAssert(student.age1 == 6) // 解析到前面的數字6 XCTAssert(student.age2 == 6) XCTAssert(student.age3 == 6) XCTAssert(student.age4 == 6) XCTAssert(student.age5 == 6) XCTAssert(student.age6 == 6) // true爲1,false爲0 XCTAssert(student.age7 == 1) // 字符串true\TRUE\YES\yes都爲1,字符串false\FALSE\NO\no都爲0 XCTAssert(student.age8 == 0) XCTAssert(student.age9 == 6) XCTAssert(student.age10 == 6) XCTAssert(student.age11 == 1565922866)
struct Student: Convertible { var height1: Float = 0.0 var height2: Float = 0.0 var height3: Float = 0.0 var height4: Float = 0.0 var height5: Float = 0.0 var height6: Float = 0.0 var height7: Float = 0.0 var height8: Float = 0.0 var height9: Float = 0.0 } let json: [String: Any] = [ "height1": "6.66suan8fa8", "height2": "0.12345678", "height3": NSDecimalNumber(string: "0.12345678"), "height4": Decimal(string: "0.12345678") as Any, "height5": 666, "height6": true, "height7": "NO", "height8": CGFloat(0.12345678), "height9": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) XCTAssert(student.height1 == 6.66) XCTAssert(student.height2 == 0.12345678) XCTAssert(student.height3 == 0.12345678) XCTAssert(student.height4 == 0.12345678) XCTAssert(student.height5 == 666.0) // true爲1.0,false爲0.0 XCTAssert(student.height6 == 1.0) // 字符串true\TRUE\YES\yes都爲1.0,字符串false\FALSE\NO\no都爲0.0 XCTAssert(student.height7 == 0.0) XCTAssert(student.height8 == 0.12345678) XCTAssert(student.height9 == 1565922866)
struct Student: Convertible { var height1: Double = 0.0 var height2: Double = 0.0 var height3: Double = 0.0 var height4: Double = 0.0 var height5: Double = 0.0 var height6: Double = 0.0 var height7: Double = 0.0 var height8: Double = 0.0 var height9: Double = 0.0 } let json: [String: Any] = [ "height1": "6.66suan8fa8", "height2": "0.1234567890123456", "height3": NSDecimalNumber(string: "0.1234567890123456"), "height4": Decimal(string: "0.1234567890123456") as Any, "height5": 666, "height6": true, "height7": "NO", "height8": CGFloat(0.1234567890123456), "height9": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) XCTAssert(student.height1 == 6.66) XCTAssert(student.height2 == 0.1234567890123456) XCTAssert(student.height3 == 0.1234567890123456) XCTAssert(student.height4 == 0.1234567890123456) XCTAssert(student.height5 == 666.0) // true爲1.0,false爲0.0 XCTAssert(student.height6 == 1.0) // 字符串true\TRUE\YES\yes都爲1.0,字符串false\FALSE\NO\no都爲0.0 XCTAssert(student.height7 == 0.0) XCTAssert(student.height8 == 0.1234567890123456) XCTAssert(student.height9 == 1565922866)
struct Student: Convertible { var height1: CGFloat = 0.0 var height2: CGFloat = 0.0 var height3: CGFloat = 0.0 var height4: CGFloat = 0.0 var height5: CGFloat = 0.0 var height6: CGFloat = 0.0 var height7: CGFloat = 0.0 var height8: CGFloat = 0.0 var height9: CGFloat = 0.0 } let json: [String: Any] = [ "height1": "6.66suan8fa8", "height2": "0.1234567890123456", "height3": NSDecimalNumber(string: "0.1234567890123456"), "height4": Decimal(string: "0.1234567890123456") as Any, "height5": 666, "height6": true, "height7": "NO", "height8": 0.1234567890123456, "height9": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) XCTAssert(student.height1 == 6.66) XCTAssert(student.height2 == CGFloat(0.1234567890123456)) XCTAssert(student.height3 == CGFloat(0.1234567890123456)) XCTAssert(student.height4 == CGFloat(0.1234567890123456)) XCTAssert(student.height5 == 666.0) XCTAssert(student.height6 == 1.0) XCTAssert(student.height7 == 0.0) XCTAssert(student.height8 == CGFloat(0.1234567890123456)) XCTAssert(student.height9 == CGFloat(1565922866))
struct Student: Convertible { var rich1: Bool = false var rich2: Bool = false var rich3: Bool = false var rich4: Bool = false var rich5: Bool = false var rich6: Bool = false } let json: [String: Any] = [ "rich1": 100, "rich2": 0.0, "rich3": "1", "rich4": NSNumber(value: 0.666), "rich5": "true", "rich6": "NO" ] let student = json.kj.model(Student.self) // 數值0爲false,數值非0都是true XCTAssert(student.rich1 == true) XCTAssert(student.rich2 == false) XCTAssert(student.rich3 == true) // 0.666是非0,因此爲true XCTAssert(student.rich4 == true) // 字符串true\TRUE\YES\yes都爲true XCTAssert(student.rich5 == true) // 字符串false\FALSE\NO\no都爲false XCTAssert(student.rich6 == false)
// 無論是String、NSString,仍是NSMutableString,都是等效支持的 struct Student: Convertible { var name1: String = "" var name2: String = "" var name3: NSString = "" var name4: NSString = "" var name5: NSMutableString = "" var name6: NSMutableString = "" var name7: String = "" var name8: String = "" var name9: String = "" } let json: [String: Any] = [ "name1": 666, "name2": NSMutableString(string: "777"), "name3": [1,[2,3],"4"], "name4": NSDecimalNumber(string: "0.123456789012345678901234567890123456789"), "name5": 6.66, "name6": false, "name7": NSURL(fileURLWithPath: "/users/mj/desktop"), "name8": URL(string: "http://www.520suanfa.com") as Any, "name9": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) XCTAssert(student.name1 == "666") XCTAssert(student.name2 == "777") // 這裏至關於默認調用了數組的description方法 XCTAssert(student.name3 == "[1, [2, 3], \"4\"]") XCTAssert(student.name4 == "0.123456789012345678901234567890123456789") XCTAssert(student.name5 == "6.66") XCTAssert(student.name6 == "false") XCTAssert(student.name7 == "file:///users/mj/desktop") XCTAssert(student.name8 == "http://www.520suanfa.com") XCTAssert(student.name9 == "1565922866")
struct Student: Convertible { var money1: Decimal = 0 var money2: Decimal = 0 var money3: Decimal = 0 var money4: Decimal = 0 var money5: Decimal = 0 var money6: Decimal = 0 var money7: Decimal = 0 var money8: Decimal = 0 } let json: [String: Any] = [ "money1": 0.1234567890123456, "money2": true, "money3": NSDecimalNumber(string: "0.123456789012345678901234567890123456789"), "money4": "0.123456789012345678901234567890123456789", "money5": 666, "money6": "NO", "money7": CGFloat(0.1234567890123456), "money8": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) XCTAssert(student.money1 == Decimal(string: "0.1234567890123456")) XCTAssert(student.money2 == 1) XCTAssert(student.money3 == Decimal(string: "0.123456789012345678901234567890123456789")) XCTAssert(student.money4 == Decimal(string: "0.123456789012345678901234567890123456789")) XCTAssert(student.money5 == 666) XCTAssert(student.money6 == 0) XCTAssert(student.money7 == Decimal(string: "0.1234567890123456")) XCTAssert(student.money8 == Decimal(string: "1565922866"))
struct Student: Convertible { var money1: NSDecimalNumber = 0 var money2: NSDecimalNumber = 0 var money3: NSDecimalNumber = 0 var money4: NSDecimalNumber = 0 var money5: NSDecimalNumber = 0 var money6: NSDecimalNumber = 0 var money7: NSDecimalNumber = 0 var money8: NSDecimalNumber = 0 } let json: [String: Any] = [ "money1": 0.1234567890123456, "money2": true, "money3": Decimal(string: "0.123456789012345678901234567890123456789") as Any, "money4": "0.123456789012345678901234567890123456789", "money5": 666.0, "money6": "NO", "money7": CGFloat(0.1234567890123456), "money8": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) XCTAssert(student.money1 == NSDecimalNumber(string: "0.1234567890123456")) XCTAssert(student.money2 == true) XCTAssert(student.money2 == 1) XCTAssert(student.money3 == NSDecimalNumber(string: "0.123456789012345678901234567890123456789")) XCTAssert(student.money4 == NSDecimalNumber(string: "0.123456789012345678901234567890123456789")) XCTAssert(student.money5 == 666) XCTAssert(student.money6 == false) XCTAssert(student.money6 == 0) XCTAssert(student.money7 == NSDecimalNumber(string: "0.1234567890123456")) XCTAssert(student.money8 == NSDecimalNumber(string: "1565922866"))
struct Student: Convertible { var money1: NSNumber = 0 var money2: NSNumber = 0 var money3: NSNumber = 0 var money4: NSNumber = 0 var money5: NSNumber = 0 var money6: NSNumber = 0 var money7: NSNumber = 0 var money8: NSNumber = 0 } let json: [String: Any] = [ "money1": 0.1234567890123456, "money2": true, "money3": Decimal(string: "0.1234567890123456") as Any, "money4": "0.1234567890123456", "money5": 666.0, "money6": "NO", "money7": CGFloat(0.1234567890123456), "money8": Date(timeIntervalSince1970: 1565922866) ] let student = json.kj.model(Student.self) XCTAssert(student.money1 == NSNumber(value: 0.1234567890123456)) XCTAssert(student.money2 == true) XCTAssert(student.money2 == 1) XCTAssert(student.money2 == 1.0) XCTAssert(student.money3 == NSNumber(value: 0.1234567890123456)) XCTAssert(student.money4 == NSNumber(value: 0.1234567890123456)) XCTAssert(student.money5 == 666) XCTAssert(student.money5 == 666.0) XCTAssert(student.money6 == false) XCTAssert(student.money6 == 0) XCTAssert(student.money6 == 0.0) XCTAssert(student.money7 == NSNumber(value: longDouble)) XCTAssert(student.money8 == NSNumber(value: 1565922866))
// 再多?都不是問題 struct Student: Convertible { var rich1: Bool = false var rich2: Bool? = false var rich3: Bool?? = false var rich4: Bool??? = false var rich5: Bool???? = false var rich6: Bool????? = false } let rich1: Int????? = 100 let rich2: Double???? = 0.0 let rich3: String??? = "0" let rich4: NSNumber?? = NSNumber(value: 0.666) let rich5: String? = "true" let rich6: String = "NO" let json: [String: Any] = [ "rich1": rich1 as Any, "rich2": rich2 as Any, "rich3": rich3 as Any, "rich4": rich4 as Any, "rich5": rich5 as Any, "rich6": rich6 ] let student = json.kj.model(Student.self) XCTAssert(student.rich1 == true) XCTAssert(student.rich2 == false) XCTAssert(student.rich3 == false) XCTAssert(student.rich4 == true) XCTAssert(student.rich5 == true) XCTAssert(student.rich6 == false)
// 支持URL和NSURL,默認會將String轉爲URL\NSURL struct Student: Convertible { var url1: NSURL? var url2: NSURL? var url3: URL? var url4: URL? } let url = "http://520suanfa.com/紅黑樹" let encodedUrl = "http://520suanfa.com/%E7%BA%A2%E9%BB%91%E6%A0%91" let json: [String: Any] = [ "url1": url, "url2": URL(string: encodedUrl) as Any, "url3": url, "url4": NSURL(string: encodedUrl) as Any ] let student = json.kj.model(Student.self) XCTAssert(student.url1?.absoluteString == encodedUrl) XCTAssert(student.url2?.absoluteString == encodedUrl) XCTAssert(student.url3?.absoluteString == encodedUrl) XCTAssert(student.url4?.absoluteString == encodedUrl)
// 支持NSData和Data,默認會將String轉爲Data\NSData struct Student: Convertible { var data1: NSData? var data2: NSData? var data3: Data? var data4: Data? var data5: NSMutableData? var data6: NSMutableData? } let utf8 = String.Encoding.utf8 let str = "RedBlackTree" let data = str.data(using: utf8)! let json: [String: Any] = [ "data1": str, "data2": data, "data3": str, "data4": NSMutableData(data: data), "data5": str, "data6": data ] let student = json.kj.model(Student.self) XCTAssert(String(data: (student.data1)! as Data, encoding: utf8) == str) XCTAssert(String(data: (student.data2)! as Data, encoding: utf8) == str) XCTAssert(String(data: (student.data3)!, encoding: utf8) == str) XCTAssert(String(data: (student.data4)!, encoding: utf8) == str) XCTAssert(String(data: (student.data5)! as Data, encoding: utf8) == str) XCTAssert(String(data: (student.data6)! as Data, encoding: utf8) == str)
// 支持Date和NSDate,默認會將毫秒數轉爲Date\NSDate struct Student: Convertible { var date1: NSDate? var date2: NSDate? var date3: Date? var date4: Date? var date5: Date? var date6: Date? var date7: Date? } let milliseconds: TimeInterval = 1565922866 let json: [String: Any] = [ "date1": milliseconds, "date2": Date(timeIntervalSince1970: milliseconds), "date3": milliseconds, "date4": NSDate(timeIntervalSince1970: milliseconds), "date5": "\(milliseconds)", "date6": NSDecimalNumber(string: "\(milliseconds)"), "date7": Decimal(string: "\(milliseconds)") as Any ] let student = json.kj.model(Student.self) XCTAssert(student.date1?.timeIntervalSince1970 == milliseconds) XCTAssert(student.date2?.timeIntervalSince1970 == milliseconds) XCTAssert(student.date3?.timeIntervalSince1970 == milliseconds) XCTAssert(student.date4?.timeIntervalSince1970 == milliseconds) XCTAssert(student.date5?.timeIntervalSince1970 == milliseconds) XCTAssert(student.date6?.timeIntervalSince1970 == milliseconds) XCTAssert(student.date7?.timeIntervalSince1970 == milliseconds)
// 遵照一下ConvertibleEnum協議便可支持帶有RawValue的Enum類型 enum Grade: String, ConvertibleEnum { case perfect = "A" case great = "B" case good = "C" case bad = "D" } struct Student: Convertible { var grade1: Grade = .perfect var grade2: Grade = .perfect } let json: [String: Any] = [ "grade1": "C", "grade2": "D" ] let student = json.kj.model(Student.self) XCTAssert(student.grade1 == .good) XCTAssert(student.grade2 == .bad) // 換個浮點數試試 enum Grade2: Double, ConvertibleEnum { case perfect = 8.88 case great = 7.77 case good = 6.66 case bad = 5.55 } struct Student2: Convertible { var grade1: Grade2 = .perfect var grade2: Grade2 = .perfect var grade3: Grade2 = .perfect var grade4: Grade2 = .perfect } let json2: [String: Any] = [ "grade1": "5.55kaka", "grade2": 6.66, "grade3": NSNumber(value: 7.77), "grade4": NSDecimalNumber(string: "8.88") ] let student2 = json2.kj.model(Student2.self) XCTAssert(student2?.grade1 == .bad) XCTAssert(student2?.grade2 == .good) XCTAssert(student2?.grade3 == .great) XCTAssert(student2?.grade4 == .perfect)
// 支持Array、NSArray、NSMutableArray與Set、NSSet、NSMutableSet之間自動轉換 struct Person: Convertible { var array1: [Int]? var array2: NSArray? var array3: NSMutableArray? var array4: [Int]? var array5: NSArray? var array6: NSMutableArray? } let array = [1, 2, 3] let json: [String: Any] = [ "array1": NSMutableArray(array: array), "array2": array, "array3": array, "array4": NSMutableSet(array: array), "array5": NSSet(array: array), "array6": Set(array), ] let person = json.kj.model(Person.self) XCTAssert(person.array1 == array) XCTAssert(person.array2 == array as NSArray) XCTAssert(person.array3 == NSMutableArray(array: array)) for i in array { XCTAssert(person.array4?.contains(i) == true) XCTAssert(person.array5?.contains(i) == true) XCTAssert(person.array6?.contains(i) == true) }
// 支持Set、NSSet、NSMutableSet與Array、NSArray、NSMutableArray之間自動轉換 struct Person: Convertible { var set1: Set<Int>? var set2: NSSet? var set3: NSMutableSet? var set4: Set<Int>? var set5: NSSet? var set6: NSMutableSet? } let array = [1, 2, 3] let json: [String: Any] = [ "set1": NSMutableSet(array: array), "set2": Set(array), "set3": Set(array), "set4": NSMutableArray(array: array), "set5": array, "set6": array ] let person = json.kj.model(Person.self) for i in array { XCTAssert(person.set1?.contains(i) == true) XCTAssert(person.set2?.contains(i) == true) XCTAssert(person.set3?.contains(i) == true) XCTAssert(person.set4?.contains(i) == true) XCTAssert(person.set5?.contains(i) == true) XCTAssert(person.set6?.contains(i) == true) }
// 支持Dictionary、NSDictionary、NSMutableDictionary之間自動轉換 struct Person: Convertible { var dict1: [String: Any]? var dict2: NSDictionary? var dict3: NSMutableDictionary? } let dict = ["no1": 100, "no2": 200] let json: [String: Any] = [ "dict1": NSMutableDictionary(dictionary: dict), "dict2": dict, "dict3": dict ] let person = json.kj.model(Person.self) for (k, v) in dict { XCTAssert(person.dict1?[k] as? Int == v) XCTAssert(person.dict2?[k] as? Int == v) XCTAssert(person.dict3?[k] as? Int == v) }