Swift中JSON转model

1.Codeble

Swift中,可以使用Codable协议来将JSON转换为model。

1
public typealias Codable = Decodable & Encodable

Codable 是一个组合协议,由 Decodable 和 Encodable 两个协议组成。作用是将 JSON 转换为 model 对象,也可以反过来将 model 对象转换为 JSON 或其它格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let jsonString = """
{
"name": "davidlii",
"email": "davidlii@sina.com",
"sex":true,
"age": 18
}
"""
// JSON中的字段可以比实体中的属性多

struct User: Codable {
let name: String
let email: String
let sex: Bool
}

do {
//1.json转Model
let data = jsonString.data(using: .utf8)!
let usr = try JSONDecoder().decode(User.self, from: data)
print(usr)

//2.model转json
let encodeData = try JSONEncoder().encode(usr)
let json = String.init(data: encodeData, encoding: .utf8)
print(json!)

}catch{
print("~some error~")
}

2.映射

如果Model中的属性名与 JSON 中的键不一致,可使用CodingKeys枚举来映射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let jsonString = """
{
"name": "davidlii",
"email": "davidlii@sina.com",
"sex":true,
}
"""

struct User: Codable {
let name: String
let emailBox: String //与JSON中不匹配
let sex: Bool

//映射键与属性
private enum CodingKeys :String, CodingKey{
case name
case emailBox = "email" //匹配不规则的JSON字段
case sex
}
}

do {
//JSON转Model
let data = jsonString.data(using: .utf8)!
let usr = try JSONDecoder().decode(User.self, from: data)
print(usr)

}catch{
print("~some error~")
}

3.自定义编解码

JSON中字段的类型可能会与model中的不同,需要我们自定义编解码,来达到二者的统一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
let jsonString = """
{
"name": "davidlii",
"sex": 0,
}
"""

struct User: Codable {
let name: String
let sex: Bool

//下面会用到
private enum CodingKeys :String, CodingKey{
case name
case sex
}
//解码
init(from decoder: Decoder) throws {
let box = try decoder.container(keyedBy: CodingKeys.self)
self.name = try box.decode(String.self, forKey: .name) //CodingKeys中定义的枚举
//先取出来Int值
let sexInt = try box.decode(Int.self, forKey: .sex)
//再转换成Bool
self.sex = (sexInt == 1)
}
//编码
func encode(to encoder: Encoder) throws {
var box = encoder.container(keyedBy: CodingKeys.self)
try box.encode(self.name, forKey: .name)
// 编码成Int
try box.encode(sex ? 1 : 0, forKey: .sex)
}
}

do {
//1.json转Model
let data = jsonString.data(using: .utf8)!
let usr = try JSONDecoder().decode(User.self, from: data)
print(usr)

//2.model转json
let encodeData = try JSONEncoder().encode(usr)
let json = String.init(data: encodeData, encoding: .utf8)
print(json!)

}catch{
print("~some error~")
}

4.数组属性

JSON中有数组类型时的处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
let jsonString = """
{
"id": 1,
"users": [
{
"name": "davidlii",
"email": "davidlii@sina.com",
"sex":true,
},
{
"name": "Het",
"email": "Het@sina.com",
"sex":false,
}
]
}
"""

//小组
struct Group: Codable {
let identifier: Int
let users:[User] // 数组

//映射键与属性
private enum CodingKeys :String, CodingKey{
case identifier = "id"
case users
}
}
//组员
struct User: Codable {
let name: String
let ema1l: String
let sex: Bool

//映射键与属性
private enum CodingKeys :String, CodingKey{
case name
case ema1l = "email" //匹配不规则的JSON字段
case sex
}
}

do {
//1.json转Model
let data = jsonString.data(using: .utf8)!
let usrs = try JSONDecoder().decode(Group.self, from: data)
print(usrs)

//2.model转json
let encodeData = try JSONEncoder().encode(usrs)
let json = String.init(data: encodeData, encoding: .utf8)
print(json!)

}catch{
print("~some error~")
}

5.可选属性

model中可选属性为空时,编码后不会包含在 JSON 数据中。解码时,JSON字段中可不传此字段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
let jsonString = """
{
"users": [
{
"name": "davidlii",
"email": "davidlii@sina.com",
"sex":true,
"age": 18
},
{
"name": "Het",
"email": "Het@sina.com",
"sex":false,
}
]
}
"""

//小组
struct Group: Codable {
let users:[User]
}
//组员
struct User: Codable {
let name: String
let email: String
let sex: Bool
let age: Int?
}

do {
//1.json转Model
let data = jsonString.data(using: .utf8)!
let usrs = try JSONDecoder().decode(Group.self, from: data)
print(usrs)

//2.model转json
let encodeData = try JSONEncoder().encode(usrs)
let json = String.init(data: encodeData, encoding: .utf8)
print(json!)

}catch{
print("~some error~")
}

输出的字符串:

1
{"users":[{"email":"davidlii@sina.com","sex":true,"age":18,"name":"davidlii"},{"name":"Het","email":"Het@sina.com","sex":false}]}

编码后,不会包含为nil的age字段。


相关参考:

#©


Swift中JSON转model
https://davidlii.cn/2018/10/01/swift-json.html
作者
Davidli
发布于
2018年10月1日
许可协议