使用 Swift Decodable 解码具有动态键值的 JSON,键值名称在 JSON 模型中的其他地方找到

问题描述

当我发出 API 请求时,我得到一个 JSON 结构,其中包含多个对象,这些对象都具有唯一的键值名称。因此我不能使用常规的 Decodable 协议将 JSON 分解为不同的实例。但是,这些键值名称可以在我可以正常访问的已知常量值下的 JSON 结构中的其他地方找到。这是我创建的一些示例代码来演示我的问题:

let jsonString = """
{
    "uniqueObjects": {
        "uniqueObject:1132435": {
            "firstName": "John"
            "lastName": "Smith"
        }
        "uniqueObject2:119672": {
            "firstName": "Jane"
            "lastName": "Doe"
        }
        "uniqueObject3:008997": {
            "firstName": "Sam"
            "lastName": "Greenfield"
        }
    }
    "keys": {
        "object1": {
            "key": "uniqueObject1:132435"
        }
        "object2": {
            "key": "uniqueObject2:119672"
        }
        "object3": {
            "key": "uniqueObject3:008997"
        }
}
"""

let jsonData = Data(jsonString.utf8)

let decodedData = try? JSONDecoder().decode(JSONData.self,from: jsonData)

print(decodedData?.uniqueObjects.firstObject.firstName ?? "No data decoded")

struct JSONData: Decodable {
    let uniqueObjects: Object
    let keys: KeyObjects
}

struct Object: Decodable {
    let firstObject: Names
    let secondobject: Names
    let thirdobject: Names
    
    private enum DynamicCodingKeys: String,CodingKey {
        case firstObject = "???" // this needs to be mapped to the unique value for object 1
        case secondobject = "??" // this needs to be mapped to the unique value for object 2
        case thirdobject = "????" // etc.
        // I don't think this works because Xcode says that the strings must be raw literals
    }
}

struct KeyObjects: Decodable {
    let object1: Key
    let object2: Key
    let object3: Key
}

struct Key: Decodable {
    let key: String
}

struct Names: Decodable {
    let firstName: String
    let lastName: String
}

在这里采用的方法绝对是错误的,它为每个唯一对象创建一个编码键,并将其名称映射到一个字符串,该字符串将以某种方式从键对象中的相对键值对中解码。 CodingKeys,至少我已经尝试过,不允许您这样做,因此我需要一种新方法来访问此代码。我还需要知道如何在解码后引用数据(现在只是打印出来)。由于我是初学者开发人员,因此非常感谢帮助和简短的解释。谢谢!

解决方法

 struct JSonResponse: Codable {
      var uniqueObjects: [String:[String: String]]
      var keys: [String:[String: String]]
 }

这样的事情可能是您最好的选择,因为您无法在编码或时间确定密钥是什么。 CodingKeys 是静态的,因此您无法根据 Json 数据更改它们。

,

除非我有误解,否则在我看来你好像把事情复杂化了。这就是我如何定义解码 json 的类型

struct Response: Codable {
    let uniqueObjects: [String: User]
    let keys: [String: ObjectKey]
}

struct ObjectKey: Codable {
    let key: String
}

struct User: Codable {
    let firstName: String
    let lastName: String
}