Swift Codable 手动解码可选变量
Swift Codable Decode Manually Optional Variable
我有以下代码:
import Foundation
let jsonData = """
[
{"firstname": "Tom", "lastname": "Smith", "age": "28"},
{"firstname": "Bob", "lastname": "Smith"}
]
""".data(using: .utf8)!
struct Person: Codable {
let firstName, lastName: String
let age: String?
enum CodingKeys : String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
firstName = try values.decode(String.self, forKey: .firstName)
lastName = try values.decode(String.self, forKey: .lastName)
age = try values.decode(String.self, forKey: .age)
}
}
let decoded = try JSONDecoder().decode([Person].self, from: jsonData)
print(decoded)
问题是它在 age = try values.decode(String.self, forKey: .age)
上崩溃了。当我执行 init
函数时,它工作正常。错误是 No value associated with key age (\"age\").
.
关于如何使它成为可选的并且在它不存在时不会崩溃的任何想法?出于其他原因,我也需要 init
函数,但只是举了一个简单的例子来解释发生了什么。
年龄可选:
let age: String?
所以尝试这样解码:
let age: String? = try values.decodeIfPresent(String.self, forKey: .age)
这是我的工作。
var age: String? = nil
age = try? container.decode(String.self, forKey: .age)
希望得到帮助。
在我的模型中,我所做的是
var title: String?
...
title = try container.decode(String?.self, forKey: .age)
而不是
name = try? container.decode(String.self, forKey: .age)
例如,出于某种原因,后端会为该键传递一个数值,例如 title: 74
。使用第一种方法,你会得到这样的错误信息(我为我的模型写了一个单元测试),你可以快速定位问题
但是,使用第二种方法try?
,这个有用的错误消息将被隐藏,不会冒泡。你仍然会得到一个有效的解码结果 title = nil
,这在大多数情况下实际上是不正确的,如果只有来自后端的 null
应该产生 nil
。
但是当然,如果你设计的是不管从后台取什么,只要type不匹配,就是一个nil
。那么我觉得第一种方法应该没有问题。
iOS 有一个内置方法,仅当值存在时才读取值。
变量年龄:字符串?
age = 尝试 container.decodeIfPresent(String.self, forKey: .age)
我有以下代码:
import Foundation
let jsonData = """
[
{"firstname": "Tom", "lastname": "Smith", "age": "28"},
{"firstname": "Bob", "lastname": "Smith"}
]
""".data(using: .utf8)!
struct Person: Codable {
let firstName, lastName: String
let age: String?
enum CodingKeys : String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
firstName = try values.decode(String.self, forKey: .firstName)
lastName = try values.decode(String.self, forKey: .lastName)
age = try values.decode(String.self, forKey: .age)
}
}
let decoded = try JSONDecoder().decode([Person].self, from: jsonData)
print(decoded)
问题是它在 age = try values.decode(String.self, forKey: .age)
上崩溃了。当我执行 init
函数时,它工作正常。错误是 No value associated with key age (\"age\").
.
关于如何使它成为可选的并且在它不存在时不会崩溃的任何想法?出于其他原因,我也需要 init
函数,但只是举了一个简单的例子来解释发生了什么。
年龄可选:
let age: String?
所以尝试这样解码:
let age: String? = try values.decodeIfPresent(String.self, forKey: .age)
这是我的工作。
var age: String? = nil
age = try? container.decode(String.self, forKey: .age)
希望得到帮助。
在我的模型中,我所做的是
var title: String?
...
title = try container.decode(String?.self, forKey: .age)
而不是
name = try? container.decode(String.self, forKey: .age)
例如,出于某种原因,后端会为该键传递一个数值,例如 title: 74
。使用第一种方法,你会得到这样的错误信息(我为我的模型写了一个单元测试),你可以快速定位问题
但是,使用第二种方法try?
,这个有用的错误消息将被隐藏,不会冒泡。你仍然会得到一个有效的解码结果 title = nil
,这在大多数情况下实际上是不正确的,如果只有来自后端的 null
应该产生 nil
。
但是当然,如果你设计的是不管从后台取什么,只要type不匹配,就是一个nil
。那么我觉得第一种方法应该没有问题。
iOS 有一个内置方法,仅当值存在时才读取值。
变量年龄:字符串?
age = 尝试 container.decodeIfPresent(String.self, forKey: .age)