【问题标题】:Using Codable on a dynamic type/object在动态类型/对象上使用 Codable
【发布时间】:2017-10-13 09:13:30
【问题描述】:

您好,我有以下结构嵌套在从 api 调用返回的更大结构中,但我无法对这部分进行编码/解码。我遇到的问题是 customKey 和 customValue 都是动态的。

{
    "current" : "a value"
    "hash" : "some value"
    "values": {
        "customkey": "customValue",
        "customKey": "customValue"
    }
}

我尝试了类似var values: [String:String] 的方法,但这显然不起作用,因为它实际上不是[String:String] 的数组。

【问题讨论】:

  • @vadian 我看不出这与任何这些问题有何重复。我修改了这个问题,现在更清楚了。
  • 我理解并重新打开了这个问题:简短回答:您不能将Codable 与动态键一起使用。
  • 你能推荐另一种方法吗?
  • 如果键是动态的,则只能使用动态集合类型,在本例中为字典。
  • 你有一个如何使用字典的例子吗?

标签: swift swift4 codable


【解决方案1】:

由于您链接到我对另一个问题的回答,我将扩展该问题以回答您的问题。

事实是,如果您知道在哪里查找,所有键在运行时都是已知的:

struct GenericCodingKeys: CodingKey {
    var intValue: Int?
    var stringValue: String

    init?(intValue: Int) { self.intValue = intValue; self.stringValue = "\(intValue)" }
    init?(stringValue: String) { self.stringValue = stringValue }

    static func makeKey(name: String) -> GenericCodingKeys {
        return GenericCodingKeys(stringValue: name)!
    }
}


struct MyModel: Decodable {
    var current: String
    var hash: String
    var values: [String: String]

    private enum CodingKeys: String, CodingKey {
        case current
        case hash
        case values
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        current = try container.decode(String.self, forKey: .current)
        hash = try container.decode(String.self, forKey: .hash)

        values = [String: String]()
        let subContainer = try container.nestedContainer(keyedBy: GenericCodingKeys.self, forKey: .values)
        for key in subContainer.allKeys {
            values[key.stringValue] = try subContainer.decode(String.self, forKey: key)
        }
    }
}

用法:

let jsonData = """
{
    "current": "a value",
    "hash": "a value",
    "values": {
        "key1": "customValue",
        "key2": "customValue"
    }
}
""".data(using: .utf8)!

let model = try JSONDecoder().decode(MyModel.self, from: jsonData)

【讨论】:

  • 非常感谢您的快速回复。如果我在 JSON 中的其他键旁边有正常可解码的值,这将如何应用,我是否为此添加了一个正常的枚举容器?
  • 我对您的新要求感到困惑。您可以编辑 JSON 以显示它的示例吗?
  • 我编辑了 JSON。我的意思是,我正在编码和解码的实际对象不仅仅是值 key-> object。 :)
  • @CodeDifferent 我的情况类似,但在我的情况下,我知道“key1”和“key2”但不知道“值”,我不知道如何调整你的代码,可以你帮忙 ?谢谢!
  • @TmSmth 没有足够的信息让我在这里提供帮助。请发布一个新问题,详细说明您的具体情况
【解决方案2】:

简化答案,它与字典 [String: String] 一起使用(字符串的 instatead 可以使用其他结构):

let jsonData = """
{
    "current": "a value",
    "hash": "a value",
    "values": {
        "key1": "customValue",
        "key2": "customValue"
    }
}
""".data(using: .utf8)!

struct MyModel: Decodable {
    var current: String
    var hash: String
    var values: [String: String]
}

let model = try JSONDecoder().decode(MyModel.self, from: jsonData)

for (key,value) in model.values {
    print("key: \(key) value: \(value)")
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-14
    • 2011-03-27
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多