gpt4 book ai didi

swift - 如何使枚举可通过其案例名称而不是其原始值进行解码?

转载 作者:行者123 更新时间:2023-11-28 07:19:00 26 4
gpt4 key购买 nike

如果我有这样的枚举:

enum SomeEnum: String {
case case1 = "raw value 1"
case case2 = "raw value 2"
}

如何使用案例名称(case1case2)而不是原始值使其符合 Decodable?例如,我可以这样使用它:

let data = Data("\"case1\"".utf8)
let decodedEnum = try! JSONDecoder().decode(SomeEnum.self, from: data) // SomeEnum.case1

编辑

我把这个添加到 SomeEnum 就像@Alexander 说的那样:

enum CodingKeys: String, CodingKey {
case case1, case2
}

但还是报错

The data couldn't be read because it isn't in the correct format.


编辑2

我尝试像@Lutz 所说的那样在 CodingKeys 中明确定义原始值,但我遇到了同样的错误。以防 JSONDecoder 不允许碎片化的 JSON,我尝试使用 SomeEnum 数组 (#"["case1", "case2"]"# ,这也没有用。

最佳答案

我调查了一下,这里的问题是您在 JSON 结果中看到的是编码的,而不是。因此,添加 CodingKeys 将无济于事。

一个稍微复杂的解决方案使用自定义协议(protocol)和相应的扩展来实现目标。

有了它,您可以声明:

    enum Test: String, CaseNameCodable {
case one = "Number One"
case two = "Number Two"
}

它会做你需要的。

下面勾画了一个完整的工作示例(在 Xcode 11.2 的 Playground 中为我工作):

    import Foundation

// A custom error type for decoding...
struct CaseNameCodableError: Error {
private let caseName: String

init(_ value: String) {
caseName = value
}

var localizedDescription: String {
#"Unable to create an enum case named "\#(caseName)""#
}
}

//
// This is the interesting part:
//

protocol CaseNameCodable: Codable, RawRepresentable , CaseIterable {}

extension CaseNameCodable {

init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let value = try container.decode(String.self)
guard let raw = Self.allCases.first(where: { $0.caseName == value })?.rawValue else { throw CaseNameCodableError(value) }
self.init(rawValue: raw)!
}

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(caseName)
}

private var caseName: String {
return "\(self)"
}
}

//
// Now you can use the protocol CaseNameCodable just like you
// would use Codable (on RawRepresentable enums only)
//

enum Test: String, CaseNameCodable {
case one = "Number One"
case two = "Number Two"
}

// EXAMPLE:

// Create a test value
let testValue = Test.one

// encode it and convert it to a String
let jsonData = try! JSONEncoder().encode(testValue)
let jsonString = String(data: jsonData, encoding: .utf8)!

print (jsonString) // prints: "one"

// decode the same data to produce a decoded enum instance
let decodedTestValue = try JSONDecoder().decode(Test.self, from: jsonData)

print(decodedTestValue.rawValue) // prints: Number One

关于swift - 如何使枚举可通过其案例名称而不是其原始值进行解码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58703221/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com