直到最近,我已经能够使用 Decodable 协议解码小写(“fooBar”)JSON 和帕斯卡大小写(“FooBar”)JSON,只需包含这样的 CodingKeys 枚举...
enum CodingKeys: String, CodingKey {
case bars = "Bars"
}
这使我能够以以下任一形式解码 JSON:
{"bars":[]}
或 {"Bars":[]}
但这对我来说不再适用了。
完整的示例如下。当我运行此代码时,仅对具有 Pascal 大小写字段名的 JSON 进行解码。解码小写 JSON 的唯一方法是将 CodingKeys 更改为小写(仅匹配定义的字段名称)或完全删除它们。
示例:
import UIKit
struct Foo: Codable {
var bars: [Bar]
enum CodingKeys: String, CodingKey {
case bars = "Bars"
}
struct Bar: Codable {
var barBaz: String
enum CodingKeys: String, CodingKey {
case barBaz = "BarBaz"
}
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let fooBars = [
"{\"bars\": [{\"barBaz\": \"abc\"}]}",
"{\"Bars\": [{\"BarBaz\": \"abc\"}]}",
"{\"Bars\": [{\"BarBaz\": \"abc\"},{\"BarBaz\": \"def\"}]}",
"{\"Bars\": []}",
"{\"bars\": []}"
]
fooBars.forEach {
if let fooBar = $0.data(using: .utf8) {
do {
let data = try JSONDecoder().decode(Foo.self, from: fooBar)
print("Success:\nFound \(data.bars.count) bar(s).\n")
} catch {
print("Fail:\n\(error)\n")
}
}
}
}
}
输出:
Fail:
keyNotFound(CodingKeys(stringValue: "Bars", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"Bars\", intValue: nil) (\"Bars\").", underlyingError: nil))
Success:
Found 1 bar(s).
Success:
Found 2 bar(s).
Success:
Found 0 bar(s).
Fail:
keyNotFound(CodingKeys(stringValue: "Bars", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"Bars\", intValue: nil) (\"Bars\").", underlyingError: nil))
我的应用程序仍然使用这种 CodingKey 方法引用旧的 Codable 类,但仍然可以工作。所以,我怀疑我在这个特定的例子中一定做错了什么。
任何人都可以解释我做错了什么吗?
我能够通过实施以下措施来实现这一目标...
enum CodingKeys: String, CodingKey {
case bars, Bars
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let bars = try? container.decode([Bar].self, forKey: .bars) {
self.bars = bars
} else if let id = try? container.decode([Bar].self, forKey: .Bars) {
self.bars = bars
}
}