由于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)
// 解析失败,所以使用默认值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)

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)
// 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)

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)
// 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)

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)
// 数值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

// 不管是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")

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

// 支持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)

Data

// 支持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

// 支持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)

Enum

// 遵守一下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)

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

// 支持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

// 支持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

// 支持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)
}

最新文章

  1. C语言 第四章 分支结构练习
  2. 2014年6月份第3周51Aspx源码发布详情
  3. Python语言特性之5:自省
  4. ActiveMQ_日志信息(五)
  5. 双向循环链表的Java版本实现
  6. 子元素的div不继承父元素的透明度
  7. 【学习笔记】【C语言】注释
  8. PHP内核探索之变量 图解
  9. iOS UIScrollView 你可能不知道的奇技淫巧
  10. (Problem 41)Pandigital prime
  11. 使MYSQL能被外部访问_xeyuu_新浪博客
  12. DataGridView显示数据的两种方法
  13. ABP领域层——工作单元(Unit Of work)
  14. Working with Entity Relations in OData
  15. python从初识到精通1
  16. HNU 13074 Goldbach’s Conjecture 解题报告
  17. linux文本处理常用指令总结
  18. HTML5 客户端存储数据的两种方式
  19. LeetCode 238. Product of Array Except Self (去除自己的数组之积)
  20. 《深入理解Java虚拟机》读书笔记3--垃圾回收算法

热门文章

  1. .Net项目中NLog的配置与使用
  2. ASP.NET Core系列(二):创建第一个.Net Core 项目
  3. ASP.NET 前端数据绑定---&lt;%#%&gt;及Eval()的使用
  4. //Thread::Stop();
  5. springboot基础(随笔)
  6. TinycoreLinux的安装使用
  7. Word公式显示为{EMBED Equation.DSMT4}
  8. MyBatis从入门到精通(十四):在MyBatis中使用类型处理器
  9. JavaScript基础学习第六天
  10. Jquery第二次考核