当使用 Swift Codable
时,您可以指定一个 keyDecodingStrategy
将snake_case 转换为camelCase。这对于字典中的键非常有用,但是有没有任何解决方案可以以类似的干净方式解码字典中的值?
我有一个枚举,它在一个地方用作键,在另一个地方用作值:
enum Foo: String, Codable, CodingKey, CaseIterable {
case bar
case bazQux // baz_qux in JSON, say
}
然后将其用作键,如下所示:
struct MyStruct: Codable {
enum Keys: String, CodingKey {
case myKey
}
let myProperty: [Bool]
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Foo.self)
myProperty = Foo.allCases.map {
try container.decode(Bool.self, forKey: $0)
}
}
}
但它也被用作这样的值:
struct Buz: Decodable {
enum CodingKeys: String, CodingKey {
case foo
}
// Note this is called using a decoder with keyDecodingStrategy = .convertFromSnakeCase
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let foo = try container.decode(Foo.self, forKey: .foo)
}
}
例如,JSON 可能包含如下一行:
"foo": "baz_qux"
仅当我将 bazQux
大小写的原始值设置为 baz_qux
时,值解码才有效。但这会破坏密钥解码。为了避免这个问题而不得不为同一件事制作两个单独的枚举也很烦人。
这样我就可以初始化与该值对应的正确模型。
我还想避免使用“hacky”解决方案......是否有一些相当优雅的方法可以很好地与 Codable
配合使用?
答案 0 :(得分:0)
结束在 scale_colour_manual()
上添加自定义解码初始值设定项:
Foo
public init(from decoder: Decoder) throws {
let rawValue = try decoder.singleValueContainer().decode(String.self)
if let foo = Self.init(rawValue: rawValue.snakeToCamelCase) {
self = foo
} else {
throw CodingError.unknownValue
}
}
是我在本地添加的 snakeToCamelCase
上的一个简单扩展方法。如果您想要一些错误处理,还需要将 String
添加到 enum CodingError: Error
。
这并不理想,但至少它不是太复杂。我宁愿依赖内置的大小写转换方法,但我在这里看不到这样做的方法。