Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift可编码:使用父项';s键作为值_Swift_Codable_Decodable_Jsondecoder - Fatal编程技术网

Swift可编码:使用父项';s键作为值

Swift可编码:使用父项';s键作为值,swift,codable,decodable,jsondecoder,Swift,Codable,Decodable,Jsondecoder,我有一个在根级别具有ID的JSON: { "12345": { "name": "Pim" }, "54321": { "name": "Dorien" } } 我的目标是使用Codable创建一个同时具有name和ID属性的用户对象数组。 struct User: Codable { let id: String let name: String } 我知道如何使用Codable,也知道如何工作。但我在这里尝试

我有一个在根级别具有ID的JSON:

{
    "12345": {
        "name": "Pim"
    },
    "54321": {
        "name": "Dorien"
    }
}
我的目标是使用Codable创建一个同时具有name和ID属性的用户对象数组。

struct User: Codable {
    let id: String
    let name: String
}
我知道如何使用Codable,也知道如何工作。但我在这里尝试的是两者的结合,我不知道下一步该怎么做

到目前为止,我得到的是:(你可以把这个贴在操场上)

这就是我想做的:

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode([User].self, from: data)
    decoded.forEach { print($0) }
    // User(id: "54321", name: "Dorien")
    // User(id: "12345", name: "Pim")
} catch {
    print("Failed to decode JSON")
}

非常感谢您提供的任何帮助。

您可以使用自定义编码密钥并按如下所示设置用户来解析未知密钥

struct CustomCodingKey: CodingKey {

    let intValue: Int?
    let stringValue: String

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

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

struct UserInfo: Codable {
    let name: String
}

struct User: Codable {
    var id: String = ""
    var info: UserInfo?

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CustomCodingKey.self)
        if let key = container.allKeys.first {
            self.id = key.stringValue
            self.info = try container.decode(UserInfo.self, forKey: key)
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CustomCodingKey.self)
        if let key = CustomCodingKey(stringValue: self.id) {
            try container.encode(self.info, forKey: key)
        }
    }
}

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode(User.self, from: data)
    print(decoded.id) // 12345
    print(decoded.info!.name) // Pim
} catch {
    print("Failed to decode JSON")
}

不过别忘了设置自定义编码器。或者用可解码的而不是可编码的。这很好。在同一个对象中获取所有属性只剩下一件事了,比如:User{let id:String,let name:String}。我相信我会找到答案的。我刚刚意识到这样我得到的是一个单用户对象,而我期待的是一个用户数组。我将更新我的问题,使之更清楚。你的回答结构越来越差
Id
name
或其他
user
相关属性应位于作为数组返回的同一对象中。如果这是不可能的,那么当前结构应该作为数组发送,否则没有选项,然后将其解码为
字典
(即
[String:UserInfo].self
),然后
将每个字典映射到
用户
。我完全同意你的观点。不幸的是,这是我必须处理的情况。。。感谢您抽出时间给出您的答案。
struct CustomCodingKey: CodingKey {

    let intValue: Int?
    let stringValue: String

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

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

struct UserInfo: Codable {
    let name: String
}

struct User: Codable {
    var id: String = ""
    var info: UserInfo?

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CustomCodingKey.self)
        if let key = container.allKeys.first {
            self.id = key.stringValue
            self.info = try container.decode(UserInfo.self, forKey: key)
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CustomCodingKey.self)
        if let key = CustomCodingKey(stringValue: self.id) {
            try container.encode(self.info, forKey: key)
        }
    }
}

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode(User.self, from: data)
    print(decoded.id) // 12345
    print(decoded.info!.name) // Pim
} catch {
    print("Failed to decode JSON")
}