如何使Swift Enum with Associated values符合Codable?

vq8itlhq  于 2023-06-21  发布在  Swift
关注(0)|答案(2)|浏览(123)

我会在一个可编码协议的结构中使用枚举。但是我不知道,hogy为enum做一个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

无法将类型“Value”的值转换为指定的类型“FormField”

2ic8powd

2ic8powd1#

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

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"
                )
            )
        }
    }
}
holgip5t

holgip5t2#

Swift 5.5+

Swift 5.5允许具有关联值的枚举自动符合Codable(如果它们的关联值是Codable):

enum Animal: Codable {
   case dog(breed: String)
   case cat(declawed: Bool)
}

let dog = Animal.dog(breed: "Husky")
let data = try! JSONEncoder().encode(dog)
let string = String(data: data, encoding: .utf8)!
print(string)

结果:

{"dog":{"breed":"Husky"}}

Swift <5.5

您必须手动实现encode(to:)init(from:),就像在this answer中一样。

相关问题