Codable使用
2018-02-28 本文已影响0人
kawa007
准备JSON数据
let sample1Json = """
{
"id": 1000,
"name": "基金1",
"review": null,
}
"""
let sample2Json = """
[
{
"id": 1000,
"name": "基金1",
"review": "收益高+期限短"
},
{
"id": 1001,
"name": "基金2",
"review": "适合短期投资"
}
]
"""
let sample3Json = """
{
"text": "Agree!Nice weather!",
"user": {
"name": "Jack",
"icon": "lufy.png"
},
"retweetedStatus": {
"text": "nice weather",
"user": {
"name": "Rose",
"icon": "nami.png"
}
}
}
"""
let sample4Json = """
{
"check0": true,
"check1": 1,
}
"""
let sample5Json = """
{
"date": "2017-11-16T02:02:55.000-08:00"
}
"""
1、基本模型解析
Sample.swift
class Sample: Codable {
var id: Int?
var name: String?
var review: String?
}
json转model,一行代码搞定
let data = sample1Json.data(using: .utf8)
do {
// decode 解码
let x: Sample = try JSONDecoder().decode(Sample.self, from: data!)
} catch {
print(error)
}
解析之后的结果如下:
(lldb) p x
(CodableDemo.Sample) $R0 = 0x00006040000b0c80 {
id = 1000
name = "基金1"
review = nil
}
(lldb)
2、模型解析-自定义key
class Sample: Codable {
var id: Int32?
var re_name: String?
var review: String?
enum CodingKeys: String, CodingKey {
case id
case re_name = "name" /// 自定义key
case review
}
}
注意:如果需要自定义key,所有key都需要在CodingKeys中定义,否则会报error: Type 'Sample' does not conform to protocol 'Decodable'
这个错误
json解析代码同上
解析结果如下:
(lldb) p x
(CodableDemo.Sample) $R0 = 0x00006000000af000 {
id = 1000
re_name = "基金1"
review = nil
}
(lldb)
3、嵌套模型解析
Status.swift
class Status: Codable {
var text: String?
var user: User?
var retweetedStatus: Status?
}
class User: Codable {
var name: String?
var icon: String?
}
json->model解析
let data = sample3Json.data(using: .utf8)
do {
let status: x = try JSONDecoder().decode(Status.self, from: data!)
print(x)
} catch {
print(error)
}
解析结果如下:
(lldb) p x
(CodableDemo.x) $R1 = 0x000060000026dc80 {
text = "Agree!Nice weather!"
user = 0x0000600000091c60 {
name = "Jack"
icon = "lufy.png"
}
retweetedStatus = 0x0000608000076380 {
text = "nice weather"
user = 0x000060800008aaf0 {
name = "Rose"
icon = "nami.png"
}
retweetedStatus = nil
}
}
(lldb)
4、模型数组
解析模型数组:
let data = sample2Json.data(using: .utf8)
do {
// decode 解码
let x: [Sample] = try JSONDecoder().decode([Sample].self, from: data!)
print(x)
} catch {
print(error)
}
解析结果:
(lldb) p x
([CodableDemo.Sample]) $R0 = 2 values {
[0] = 0x00006080000aace0 {
id = 1000
re_name = "基金1"
review = "收益高+期限短"
}
[1] = 0x00006000000a92a0 {
id = 1001
re_name = "基金2"
review = "适合短期投资"
}
}
(lldb)
5、自定义编码解码方法
如果JSON数据不能按预期解析,可以通过自定义编码解码方法,得到预期的解析结果
class Sample: Codable {
var id: Int?
var name: String?
var review: String?
enum CodingKeys: String, CodingKey {
case id
case name
case review
}
// 自定义编码方法
public func encode(to encoder: Encoder) throws {
// 使用CodingKeys创建编码器
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: CodingKeys.id)
try container.encode(name, forKey: CodingKeys.name)
try container.encode(review, forKey: CodingKeys.review)
}
// 自定义解码方法
public required init(from decoder: Decoder) throws {
// 使用CodingKeys创建解码器
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: CodingKeys.id)
name = try container.decode(String.self, forKey: CodingKeys.name)
review = try container.decode(String.self, forKey: CodingKeys.review)
}
}
6、日期解析
Sample.swift
class Sample: Codable {
var date: String?
enum CodingKeys: String, CodingKey {
case date
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let dateString = try container.decode(String.self, forKey: CodingKeys.date1)
let format = DateFormatter()
format.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let tempDate = format.date(from: dateString)
format.dateFormat = "yyyy-MM-dd HH:mm:ss"
date = format.string(from: tempDate!)
}
}
解析:
let data = sample5Json.data(using: .utf8)
do {
let decoder = JSONDecoder()
let x: Sample = try decoder.decode(Sample.self, from: data!)
print(x)
} catch {
print(error)
}
解析结果:
(lldb) p x
(CodableDemo.Sample2) $R0 = 0x000060800024fea0 {
date1 = "2017-11-16 18:02:55"
}
(lldb)
7、Bool值解析
codable只能解析true/false,其他类型(例如:1/0)的值会报类型不匹配的错误Expected to decode Bool but found a number instead.
,如果后台返回的类型不是true/false需要额外处理
Sample.swift
class Sample: Codable {
var check0: Bool?
var check1: Bool?
enum CodingKeys: String, CodingKey {
case check0
case check1
}
/// 自定义解码方法,处理Bool值为1/0的情况
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
check0 = try container.decode(Bool.self, forKey: CodingKeys.check0)
check1 = (try container.decode(Int.self, forKey: CodingKeys.check1) == 1) ? true : false
}
}
解析:
let data = sample4Json.data(using: .utf8)
do {
let status: Sample1 = try JSONDecoder().decode(Sample1.self, from: data!)
print(status)
} catch {
print(error)
}
解析结果:
(lldb) p status
(CodableDemo.Sample) $R0 = 0x000060c000024c80 {
check0 = true
check1 = true
}
8、继承
注意:继承的类使用codable解析,子类的属性无法正确赋值,通过自定义子类的解码方法可实现继承的类也能使用codable正确解析
具体实现如下
class
class Dog: Codable {
var name: String?
var age: Int?
}
class HSQ: Dog {
var IQ: Int?
private enum CodingKeys: String, CodingKey {
case IQ
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
IQ = try container.decode(Int.self, forKey: CodingKeys.IQ)
try super.init(from: decoder)
}
}
解析
let data = sample6Json.data(using: .utf8)
do {
let decoder = JSONDecoder()
let x: HSQ = try decoder.decode(HSQ.self, from: data!)
print(x)
} catch {
print(error)
}
解析结果:
(lldb) p x
(CodableDemo.HSQ) $R1 = 0x00006000000875d0 {
CodableDemo.Dog = {
name = "基金1"
age = 2
}
IQ = -10
}
(lldb)
参考: