Swift 使用 Codable 解析 JSON
2019-03-20 本文已影响0人
MonkeyBread
示例1:
- JSON
let jsonData: Data = """
{
"name": "MonkeyBread",
"address": "China",
"email": "12345@gamil.com",
}
""".data(using: .utf8)!
- Model
struct User: Codable {
let name: String
let address: String
let email: String
}
- 解析
let user = try? JSONDecoder().decode(User.self, from: jsonData)
JSON 与 Model 完全一致,这是最基础的 JSON 解析。
示例2:
- JSON
let jsonData: Data = """
{
"name": "MonkeyBread",
"email": "12345@gamil.com",
"addr": {
"country": "China",
"city": "Beijing",
"lat": "123",
"lng": "456",
}
}
""".data(using: .utf8)!
- Model
struct Address: Codable {
let country: String
let city: String
let latitude: String
let longitude: String
}
struct User: Codable {
let userName: String
let email: String
let address: Address
}
- 解析
struct Address: Codable {
let country: String
let city: String
let latitude: String
let longitude: String
private enum CodingKeys: String, CodingKey {
case country
case city
case latitude = "lat"
case longitude = "lng"
}
}
struct User: Codable {
let userName: String
let email: String
let address: Address
private enum CodingKeys: String, CodingKey {
case userName = "name"
case email
case address = "addr"
}
}
let user = try? JSONDecoder().decode(User.self, from: jsonData)
JSON 与 Model 不一致的情况,可通过 CodingKeys 枚举对应,多层嵌套的情况也同样适用。
需要注意的是:如果重写 CodingKeys enum 需要包含 Model 中所有属性。
示例3:
- JSON
let jsonData: Data = """
{
"name": "MonkeyBread",
"email": "12345@gamil.com",
"addr": {
"country": "China",
"city": "Beijing",
"lat": "123",
"lng": "456"
}
}
""".data(using: .utf8)!
- Model
struct User: Codable {
let userName: String
let email: String
let country: String
let city: String
let latitude: String
let longitude: String
}
- 解析:
struct User: Codable {
var userName: String = ""
var email: String = ""
var country: String = ""
var city: String = ""
var latitude: String = ""
var longitude: String = ""
private enum UserKeys: String, CodingKey {
case userName = "name"
case email
case addr
}
private enum AddressKeys: String, CodingKey {
case country
case city
case latitude = "lat"
case longitude = "lng"
}
init(from decoder: Decoder) throws {
if let userContainer = try? decoder.container(keyedBy: UserKeys.self) {
self.userName = try userContainer.decode(String.self, forKey: .userName)
self.email = try userContainer.decode(String.self, forKey: .email)
if let addressContainer = try? userContainer.nestedContainer(keyedBy: AddressKeys.self, forKey: .addr) {
self.country = try addressContainer.decode(String.self, forKey: .country)
self.city = try addressContainer.decode(String.self, forKey: .city)
self.latitude = try addressContainer.decode(String.self, forKey: .latitude)
self.longitude = try addressContainer.decode(String.self, forKey: .longitude)
}
}
}
}
if let user = try? JSONDecoder().decode(User.self, from: jsonData) {
print(user.userName)
print(user.email)
print(user.country)
print(user.latitude)
print(user)
}
示例中的 addr 参数包含了地理位置信息,一般情况都会按照 示例2 的方式解析,但如果项目中仅用到了 country 参数,创建 Address 类来接收参数就显得很累赘了,此示例就是将 addr 参数与 User 参数合并成了一层,省去了 Address 类。