【发布时间】:2019-12-01 21:01:36
【问题描述】:
我遇到的端点可能会返回两种不同 JSON 之一,具体取决于用户是否需要回答安全问题:
// possible response (payload) #1
{
"token": "123lknk123kj1n13132"
}
// possible response (payload) #2
{
"securityQuestion": "What is your mother's maiden name?"
}
我的目标是创建一个模型,该模型将根据有效负载中存在的密钥(即"token" 或"securityQuestion")对 JSON 进行不同的解码。 目前,我遇到了一个解析错误,我不知道为什么。
我的灵感来自对 SO 上一个问题的精心设计的回答。我当前的代码是它的修改版本,(理论上)符合我的需要。我希望我的代码的最终版本保留这种结构。我的代码如下:
/**
Enumerates the possible payloads received from Server
- success: Successful payload that contains the user's access token
- securityQuestion: Payload that contains the security question that the user has to answer to receive a token
*/
enum PayloadType: String, Decodable {
case success
case securityQuestion
}
protocol Payload: Decodable { static var payloadType: PayloadType { get } }
/// Model for successful response sent by the server.
struct SuccessfulResponse: Payload {
static let payloadType = PayloadType.success
let token: String
}
/// Model for response sent by the server which includes a security question
struct SecurityQuestionResponse: Payload {
static let payloadType = PayloadType.securityQuestion
let securityQuestion: String
}
/// Model for building a response sent by the server.
struct Response: Decodable {
let data: Payload
let payloadType: PayloadType
init(from decoder: Decoder) throws {
// NOTE*: This part is a little shaky, maybe this is where I am going wrong
let values = try decoder.container(keyedBy: CodingKeys.self)
self.payloadType = try values.decode(PayloadType.self, forKey: .payloadType)
// payloadType will determine how the JSON is decoded
switch self.payloadType
{
case .success:
self.data = try values.decode(SuccessfulResonse.self, forKey: .data)
case .securityQuestion:
self.data = try values.decode(SecurityQuestionResponse.self, forKey: .data)
}
}
private enum CodingKeys: String, CodingKey {
case data
case payloadType
}
}
【问题讨论】:
-
不要认为这对
Codable最好,您需要使用 SwiftyJSON/JSONSerialization 1 键不值得那么头痛 -
你是对的,仅仅 1 把钥匙是不值得的。这种架构背后的基本原理是,服务器实际上可以发送多个响应,每个响应都有很多键。为了简洁起见,我决定不在这篇文章中列出它们,并避免过多的代码使访问者不堪重负。如果可能的话,我想避免使用外部库。此外,我对 JSONSerialization 并不精通,它可能需要我更改此模型的架构。你能帮我假设这个结构保持不变吗?
-
struct Root:Codable { let token,securityQuestion:String?} -
这是我尝试的第一件事。将
securityQuestion/token设为可选将不起作用。不知道为什么 -
@DataDaddy 如果您有有效的
JSON数据,请从该网址尝试app.quicktype.io