在 Swift 中,如何使用 Decodable 协议解码小写和帕斯卡大小写 JSON?

问题描述 投票:0回答:1

直到最近,我已经能够使用 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 类,但仍然可以工作。所以,我怀疑我在这个特定的例子中一定做错了什么。

任何人都可以解释我做错了什么吗?

ios json swift codable
1个回答
0
投票

我能够通过实施以下措施来实现这一目标...

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
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.