0

我想从具有默认实现属性的可编码结构中制作字典。

struct MyStruct: MyStructProtocol {
    var value: String
}

该结构实现了一个协议。该协议有两个变量。一个变量具有默认实现。

protocol MyStructProtocol: Encodable {
    var defaultValue: String { get }
    var value: String { set get }
}

extension MyStructProtocol {
    var defaultValue: String { return "my-default-value" }
}

为此,我使用如何使用 Swift 的 Codable 编码到字典Encodable中的扩展?:

extension Encodable {
    var asDictionary: [String: Any]? {
        guard let data = try? JSONEncoder().encode(self) else { return nil }
        return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
    }
}

因此,当我实例化结构并将其“编码”为字典时:

let myStruct = MyStruct(value: "my-value")
let myStructDictionary = myStruct.asDictionary

那么defaultValue不包括:

["value": "my-value"]

但我需要的是(包括默认值):

["defaultValue": "my-default-value", "value": "my-value"]
4

3 回答 3

3

合成编码器仅考虑结构中的成员,而不考虑协议扩展中的任何属性或计算属性。

您必须编写一个自定义初始化程序。而且我更愿意让结构采用Encodable而不是协议。

struct MyStruct: MyStructProtocol, Encodable {
    var value: String

    private enum CodingKeys: String, CodingKey { case value, defaultValue }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(value, forKey: .value)
        try container.encode(defaultValue, forKey: .defaultValue)
    }
}

protocol MyStructProtocol { ...
于 2019-04-25T13:30:34.950 回答
0

Encodable不会识别计算属性。要解决此问题,请覆盖encode(to:)官方文档中所示的函数https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

编辑:问题的可能解决方案: 如何在可编码结构中使用计算属性(swift)

于 2019-04-25T13:22:49.593 回答
0

这是因为默认值 fordefaultValue已经在协议的扩展中实现,这意味着它是一个计算属性

struct MyStruct: MyStructProtocol {
    var value: String

    enum CodingKeys: String, CodingKey {
        case value
        case defaultValue = "my-default-value"
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(value, forKey: .value)
        try container.encode(defaultValue, forKey: .defaultValue)
    }
}
于 2019-04-25T13:32:47.323 回答