如何使具有关联值的 Swift 枚举符合 Codable?

How to make a Swift Enum with Associated values conform to Codable?

我会在具有可编码协议的结构中使用枚举。但我不知道,我想为枚举做一个 init。如果我没有 init.

,编译器会引发错误

这里的目标是 UpdateIn 类型中的 value 参数可以是两个东西,字符串或 FormFiled 结构。

你知道如何进行初始化吗?

struct UpdateIn: Content {
    var keyPath: [String]
    var value: Value
    var operation: String
}

enum Value: Decodable {
    init(from decoder: Decoder) throws {
        <#code#>
    }
    
  case str(String)
  case formField(FormField)
}

struct FormField: Content {
    var name: String
    var type: String
    var options: [String: FormFieldOption]?
    var selectedOption: String?
    var visibleIfIndIsVisible: Int?
    var ind: Int
    var mandatory: Bool // TODO: isMandatory
    var dateCreatedAt: Date?
    var selectItemOtherArbitraryValueEnable: Bool?
    var regex: String?
    var hasImage: Bool?
    var defaultFormFieldOptionId: String?
}

根据回答我尝试提取值并分配给特定变量,但它被拒绝了,你知道为什么吗?

let formField: FormField = params.value

Cannot convert value of type 'Value' to specified type 'FormField'

你只需要切换你的枚举关联值:

enum Value: Codable {
    case str(String)
    case formField(FormField)
    private enum CodingKeys: String, CodingKey {
        case str, formField
    }
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        switch self {
        case let .str(string):
            try container.encode(string, forKey: .str)
        case let .formField(field):
            try container.encode(field, forKey: .formField)
        }
    }
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        switch container.allKeys.first {
        case .str:
            self = try .str(container.decode(String.self, forKey: .str))
        case .formField:
            self = try .formField(container.decode(FormField.self, forKey: .formField))
        default:
            throw DecodingError.dataCorrupted(
                .init(
                    codingPath: container.codingPath,
                    debugDescription: "invalid data"
                )
            )
        }
    }
}