由于JSON格式能表达的数据类型是比较有限的,所以服务器返回的JSON数据有时无法自动转换成客户端想要的数据类型。
- 比如服务器返回的时间可能是个毫秒数
1565480696
,但客户端想要的是Date
类型
- 再比如客户端想要的是浮点数
Double
类型,但服务器返回的可能是字符串类型"6.45"
- 再比如客户端想要的是
Bool
类型,但服务器返回的可能是"true"
、"1"
、0
- 再比如客户端想要的是高精度浮点数
NSDecimalNumber
类型,服务器为了维持精度可能返回字符串"0.1234567890123456789"
- 上述不同类型之间的匹配转换问题,KakaJSON已经内置了常用的解析功能,全部自动转换,不用做任何额外的配置。本文会介绍一些常见的数据类型匹配、转换功能。
Int
| 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) |
| |
| XCTAssert(student.age1 == 6) |
| |
| XCTAssert(student.age2 == 6) |
| XCTAssert(student.age3 == 6) |
| XCTAssert(student.age4 == 6) |
| XCTAssert(student.age5 == 6) |
| XCTAssert(student.age6 == 6) |
| |
| XCTAssert(student.age7 == 1) |
| |
| XCTAssert(student.age8 == 0) |
| XCTAssert(student.age9 == 6) |
| XCTAssert(student.age10 == 6) |
| XCTAssert(student.age11 == 1565922866) |
Float
| 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) |
| |
| XCTAssert(student.height6 == 1.0) |
| |
| XCTAssert(student.height7 == 0.0) |
| XCTAssert(student.height8 == 0.12345678) |
| XCTAssert(student.height9 == 1565922866) |
Double
| 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) |
| |
| XCTAssert(student.height6 == 1.0) |
| |
| XCTAssert(student.height7 == 0.0) |
| XCTAssert(student.height8 == 0.1234567890123456) |
| XCTAssert(student.height9 == 1565922866) |
CGFloat
| 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)) |
Bool
| 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) |
| |
| XCTAssert(student.rich1 == true) |
| XCTAssert(student.rich2 == false) |
| XCTAssert(student.rich3 == true) |
| |
| XCTAssert(student.rich4 == true) |
| |
| XCTAssert(student.rich5 == true) |
| |
| XCTAssert(student.rich6 == false) |
String
| |
| |
| 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") |
| |
| 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") |
Decimal
| 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")) |
NSDecimalNumber
| 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")) |
NSNumber
| 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)) |
Optional
| |
| |
| 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
| |
| |
| 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) |
Data
| |
| |
| 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
| |
| |
| 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) |
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) |
Enum数组
| enum Grade: String, ConvertibleEnum { |
| case perfect = "A" |
| case great = "B" |
| case good = "C" |
| case bad = "D" |
| } |
| |
| struct Student: Convertible { |
| var name: String? |
| var grades: [Grade]? |
| } |
| |
| let json: [String: Any] = [ |
| "name": "Jack", |
| "grades": ["D", "B"] |
| ] |
| |
| let stu = json.kj.model(Student.self) |
| XCTAssert(stu.name == "Jack") |
| XCTAssert(stu.grades?[0] == .bad) |
| XCTAssert(stu.grades?[1] == .great) |
字典嵌套Enum
| enum Grade: String, ConvertibleEnum { |
| case perfect = "A" |
| case great = "B" |
| case good = "C" |
| case bad = "D" |
| } |
| |
| struct Student: Convertible { |
| var name: String? |
| var grades: [String: Grade]? |
| } |
| |
| let json: [String: Any] = [ |
| "name": "Jack", |
| "grades": ["2019": "D", "2020": "B"] |
| ] |
| |
| let stu = json.kj.model(Student.self) |
| XCTAssert(stu.name == "Jack") |
| XCTAssert(stu.grades?["2019"] == .bad) |
| XCTAssert(stu.grades?["2020"] == .great) |
字典嵌套Enum数组
| enum Grade: String, ConvertibleEnum { |
| case perfect = "A" |
| case great = "B" |
| case good = "C" |
| case bad = "D" |
| } |
| |
| struct Student: Convertible { |
| var name: String? |
| var grades: [String: [Grade?]]? |
| } |
| |
| let json: [String: Any] = [ |
| "name": "Jack", |
| "grades": ["2019": ["A", "B"], "2020": ["C", "D"]] |
| ] |
| |
| let stu = json.kj.model(Student.self) |
| XCTAssert(stu.name == "Jack") |
| XCTAssert(stu.grades?["2019"]?[0] == .perfect) |
| XCTAssert(stu.grades?["2019"]?[1] == .great) |
| XCTAssert(stu.grades?["2020"]?[0] == .good) |
| XCTAssert(stu.grades?["2020"]?[1] == .bad) |
Array
| |
| |
| 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
| |
| |
| 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
| |
| |
| 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) |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步