没有 CodingKeys 的 Swift 自定义可解码初始值设定项

标签 swift decodable

假设我有以下可解码结构作为示例,说明我正在尝试做的事情:

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:) ;或
  • 您同时采用 EncodableDecodable (或只是到 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/

    相关文章:

    ios - 如何在 Swift 中将计步器重置为 0?我正在使用 CMPedometer()

    json - 如何在 Swift 中解码具有许多唯一键的嵌套 JSON?

    swift - 试图在 Swift 中使一个类可编码,但它的格式不正确?

    Swift Decodable,Endpoint返回完全不同的类型

    swift - 如何在 'pure' Swift 中创建一个弱协议(protocol)引用(没有@objc)

    objective-c - 如何在 Swift 中将属性声明为函数?

    ios - 为什么我的 UITableView 会出现 NSInternalInconsistencyException 异常?

    ios - Swift:将 NSDictionary 保存到文件中,因为 NSUserDefaults 会变慢

    json - 如果第一次解码失败使用 Combine 和 Swift 解码另一个响应

    ios - 在 Swift 中从多个服务解码 JSON 的更简单方法