可选键的默认枚举值

Default enum value for optional key

我有一个 JSON 对象,它总是有 text,有时有一个 format 键,如果没有,我想使用 .regular我的 SubStep.Format 枚举的案例。

我知道我需要覆盖 SubStep 中的 init 但我该怎么做才能检测到格式键,如果它为零,请使用 .regular,并且然后解码一直存在的 text 密钥?

谢谢

struct SubStep: Decodable {
    enum Format: String, Decodable {
        case bold = "bold"
        case regular = "regular"

        init(from decoder: Decoder) {
            do {
                let label = try decoder.singleValueContainer().decode(String.self)
                self = Format(rawValue: label) ?? .regular
            } catch {
                self = .regular
            }
        }
    }

    let format: SubStep.Format
    let text: String

    init(from decoder: Decoder) throws {
       // something in here
    }
}

您不需要为 Format 创建自定义 init(from:) 方法,您只需要为 SubStep 创建一个方法。您需要使用 container.decodeIfPresent(_:forKey:) 来解码您的 JSON 中可能不存在的密钥,在这种情况下它 returns nil.

struct SubStep: Decodable {
    enum Format: String, Decodable {
        case bold
        case regular
    }

    let format: SubStep.Format
    let text: String

    private enum CodingKeys: String, CodingKey {
        case text, format
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.text = try container.decode(String.self, forKey: .text)
        self.format = try container.decodeIfPresent(Format.self, forKey: .format) ?? .regular
    }
}

与您的问题无关,但您无需为 enum 个案例提供 String rawValue,如果它们的 rawValue 与案例名称完全匹配,则编译器将为您自动合成。

作为替代解决方案,您不必在解析期间插入默认值 - 您可以改用计算的 属性。

struct SubStep: Decodable {
    enum Format: String, Decodable {
        case bold
        case regular
    }

    private let formatOptional: Format?
    let text: String

    private enum CodingKeys: String, CodingKey {
        case formatOptional = "format"
        case text
    }

    var format: Format {
        return formatOptional ?? .regular
    }
}