假设我有以下可解码结构作为示例,说明我正在尝试做的事情:
struct Object: Decodable {
var id: String
var name: String
}
和这个 JSON:[
{
"id": "a",
"name": "test"
},
{
"id": "b",
"name": null
}
]
注意 name 属性可以是 null
有时。这通常会正常工作,因为 json 键与结构属性名称匹配,所以我不需要 CodingKey
枚举,但 name
属性有时可以为空。然而,而不是制作 name
可选,我想替换一个默认字符串,所以我需要一个自定义初始化程序:struct Object: Decodable {
var id: String
var name: String
init(from decoder: Decoder) throws {
...
self.name = <value from decoder> ?? "default name"
...
}
}
但这需要一个 CodingKey
目的。我正在使用默认键。我需要一个 CodingKey
现在也枚举?即使我所有的 key 都匹配?或者有没有办法自定义Decodable
初始值设定项仅按原样使用键?我可以使用某种默认容器吗?
let container = try decoder.container(keyedBy: <defaultContainer???>)
我尝试使用这两种变体,但都没有奏效:let container = try decoder.singleValueContainer()
let container = try decoder.unkeyedContainer()
我如何定制
Decodable
初始化还有使用默认键?
最佳答案
问题是CodingKeys
只有在没有完全手动符合相关协议(protocol)的情况下才会自动为您生成。 (这对于 Objective-C 开发人员来说非常熟悉,如果您手动实现所有相关的访问器方法,则不会自动合成属性的支持 ivar。)
因此,在以下场景中,CodingKeys
不会自动为您创建:
Decodable
并实现您自己的 init(from:)
; Encodable
并实现您自己的 encode(to:)
;或 Encodable
和 Decodable
(或只是到 Codable
)并实现您自己的 init(from:)
和 encode(to:)
. 因此,您的情况属于上述第一种情况。
有人建议您可以通过采用
Codable
来解决您的难题。 ,即使你只实现了 init(from:)
并且大概不打算使用 Encodable
行为。实际上,这依赖于您不打算真正使用的协议(protocol)的副作用。真的没有太大关系,采用
Codable
有效,但继续定义您的 CodingKeys
可能被认为是“更正确的”。 ,而不是依赖于未实现的 Encodable
副作用:struct Object: Decodable {
var id: String
var name: String
enum CodingKeys: String, CodingKey {
case id, name
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(String.self, forKey: .id)
name = (try? container.decode(String.self, forKey: .name)) ?? "Default Value"
}
}
关于没有 CodingKeys 的 Swift 自定义可解码初始值设定项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61234527/