Ios 解析动态JSON的模型
我访问的端点可能返回两个不同JSON中的一个,这取决于用户是否需要回答安全问题:Ios 解析动态JSON的模型,ios,json,swift,parsing,Ios,Json,Swift,Parsing,我访问的端点可能返回两个不同JSON中的一个,这取决于用户是否需要回答安全问题: // possible response (payload) #1 { "token": "123lknk123kj1n13132" } // possible response (payload) #2 { "securityQuestion": "What is your mother's maiden name?" } 我的目标是创建一个模型,根据有效负载中存在的密钥对JSON进行不同的解
// possible response (payload) #1
{
"token": "123lknk123kj1n13132"
}
// possible response (payload) #2
{
"securityQuestion": "What is your mother's maiden name?"
}
我的目标是创建一个模型,根据有效负载中存在的密钥对JSON进行不同的解码(即“token”
或“securityQuestion”
)目前,我收到一个解析错误,我不知道原因。
我的灵感来自于对上一个问题的精心设计的回答。我当前的代码是它的一个修改版本,它(理论上)符合我的需要。我希望我的代码的最终版本保留这种结构。我的代码如下:
/**
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
}
}
在发布这个问题之前,我查看了各种类似的帖子(,),但没有一篇真正符合需要。我想建议一种不同的方法,不是更简单,而是更易于使用,至少对我来说更清楚
struct Token: Codable {
let token: String?
}
struct SecurityQuestion:Codable {
let securityQuestion: String?
}
在请求函数中添加以下内容
URLSession.shared.dataTask(with: url, completionHandler: {data,response,error in
do {
let responseObject = try JSONDecoder().decode(Token.self, from: data!)
let token = responseObject.token
print(token)
} catch let parseError {
print(parseError)
do{
let responseObject = try JSONDecoder().decode(SecurityQuestion.self, from: data!)
let securityQuestion = responseObject.securityQuestion
print(securityQuestion)
}catch{
print(error)
}
}
})
主要思想是使用catch块尝试另一种解码类型,因为第一种解码类型失败,如果您有许多不同的响应,您可以使用更多catch块来执行新的解码类型,我想建议一种不同的方法,不是更简单,而是更易于使用,至少对我来说更清楚
struct Token: Codable {
let token: String?
}
struct SecurityQuestion:Codable {
let securityQuestion: String?
}
在请求函数中添加以下内容
URLSession.shared.dataTask(with: url, completionHandler: {data,response,error in
do {
let responseObject = try JSONDecoder().decode(Token.self, from: data!)
let token = responseObject.token
print(token)
} catch let parseError {
print(parseError)
do{
let responseObject = try JSONDecoder().decode(SecurityQuestion.self, from: data!)
let securityQuestion = responseObject.securityQuestion
print(securityQuestion)
}catch{
print(error)
}
}
})
其主要思想是使用catch块尝试另一种解码类型,因为第一种解码类型失败,如果您有许多不同的响应,您可以使用更多catch块来执行新的解码类型,不要认为这对
Codable
来说是最好的,您需要使用SwiftyJSON/JSONSerialization 1键不值得这么头痛您是对的,仅仅用一把钥匙是不值得的。这种架构背后的基本原理是,服务器实际上可以发送多个响应,每个响应都有许多密钥。为了简洁起见,我决定不在这篇文章中列出它们,也为了避免访问者被太多的代码压垮。如果可能的话,我希望避免使用外部库。另外,我对JSONSerialization不太熟悉,这可能需要我更改此模型的体系结构。你能帮我假设这个结构保持不变吗?struct Root:Codable{let token,securityQuestion:String?}
这是我尝试的第一件事。将securityQuestion
/token
设置为可选将不起作用。不确定why@DataDaddy如果您拥有有效的JSON
数据,请从此URL尝试。不要认为这是Codable
的最佳选择。您需要使用快速JSON/JSONSerialization 1键不值得这么头痛。您是对的,仅使用1键是不值得的。这种架构背后的基本原理是,服务器实际上可以发送多个响应,每个响应都有许多密钥。为了简洁起见,我决定不在这篇文章中列出它们,也为了避免访问者被太多的代码压垮。如果可能的话,我希望避免使用外部库。另外,我对JSONSerialization不太熟悉,这可能需要我更改此模型的体系结构。你能帮我假设这个结构保持不变吗?struct Root:Codable{let token,securityQuestion:String?}
这是我尝试的第一件事。将securityQuestion
/token
设置为可选将不起作用。不确定why@DataDaddy如果您有有效的JSON
数据,请从此URL尝试,这是一个可行的解决方案。在这里,我将保持开放的心态,并将其标记为公认的答案,尽管我注意到的一件事是,如果有多个键(为了简洁起见,我没有在帖子中包含),那么do catch语句的嵌套将很快变得丑陋,这是真的,但对于键,它将位于init(from:Decode)中
func我有一个模型,其中解码的func比结构定义大,因为端点可以为相同的值返回字符串、doblue、int或bool,所以如果进行痛苦的解码,这是一个可行的解决方案。在这里,我将保持开放的心态,并将其标记为公认的答案,尽管我注意到的一件事是,如果有多个键(为了简洁起见,我没有在帖子中包含),那么do catch语句的嵌套将很快变得丑陋,这是真的,但对于键,它将位于init(from:Decode)中
func我有一个模型,其中解码的func比结构定义大,因为端点可以为相同的值返回字符串、doblue、int或bool,所以如果一个完整的解码