问题描述
当我发出 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
}