提问人:Ajmal Orawala 提问时间:3/17/2022 最后编辑:Ajmal Orawala 更新时间:3/17/2022 访问量:2015
Swift5:如何将此 JSON 响应处理到 Swift 数据模型中
Swift5 : How to handle this JSON response into Swift Data Model
问:
我是 Swift 的新手,所以如果这是一个愚蠢的问题,请原谅我 如何将这类响应处理成数据模型,响应是这样的:
{
"id" = 1;
count = "";
data = "[{"key":"value","key":"value".......}]";
message = SUCCESS;
"response_code" = 1;
}
AlamofireRequest 获取响应并打印它,但是当使用 responseDecodable 时,没有任何反应,Alamofire 请求的代码如下:
let request = AF.request(urlString!,method: .get)
request.responseJSON { (data) in
print(data)
}
request.responseDecodable(of: Test.self) { (response) in
guard let getData = response.value else {return}
print(getData.all[0].firstName) //Nothing prints
}
这就是数据模型的样子:
struct Test: Decodable {
let firstName: String
enum CodingKeys: String, CodingKey {
case firstName = "first_name"
//firstname is inside data of json
}
}
struct Getdata: Decodable {
let all : [Test]
enum CodingKeys: String, CodingKey {
case all = "data"
}
}
想要访问数据中的值并打印它。请阐明一下!
答:
试图解决上面的问题和评论,第一件事是获取一些有效的 JSON。可能是您的 API 正在提供非 JSON 数据,在这种情况下,此答案或使用 AlamoFire 对其进行解码都不起作用。但是,将上述格式化为 JSON,以我对它含义的最佳猜测,将给出:
let json = """
{
"id": 1,
"count": "",
"data": [
{
"key1": "value1",
"key2": "value2"
}
],
"message": "SUCCESS",
"response_code": 1
}
"""
在这一点上,更明显的是,键下的内容不是上面定义的数组,而是一个字典数组(在示例中,数组中只有一个 enry)。因此,有必要重新指定数据模型。对于这么简单的事情,对于上面提到的用例,没有真正的理由选择多种类型,所以我们将重新定义 Getdata(尽管我不喜欢它,但我坚持使用您的命名):data
Test
struct Getdata: Decodable {
let all : [[String:String]]
enum CodingKeys: String, CodingKey {
case all = "data"
}
}
为了测试解码,让我们使用标准的 JSONDecoder(我手边没有 AlamoFire 的 Playground,因为我永远不会使用它):
do {
let wrapper = try JSONDecoder().decode(Getdata.self, from: Data(json.utf8))
print(wrapper.all)
} catch {
print("Decoding error \(error.localizedDescription)")
}
这输出
[[“key1”: “值 1”, “key2”: “值 2”]]
正如预期的那样。
现在有一个有效的JSON解码解决方案,如果你愿意,应该很容易将其放入AlamoFire API中。尽管如果后端确实提供了格式错误的 JSON,这是行不通的,您必须更改后端,使用自己的解码器对其进行解码或将其修改为有效的 JSON。
评论
在原来的问题中犯了很多愚蠢的错误,还有很长的路要走
正如@flanker所建议的那样,我确实将数据模型重新指定为
struct Test : Codable {
let id : String?
let message : String?
let data : String?
let count : String?
let response_code : String?
enum CodingKeys: String, CodingKey {
case id = "$id"
case message = "message"
case data = "data"
case count = "count"
case response_code = "response_code"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decodeIfPresent(String.self, forKey: .id)
message = try values.decodeIfPresent(String.self, forKey: .message)
data = try values.decodeIfPresent(String.self, forKey: .data)
count = try values.decodeIfPresent(String.self, forKey: .count)
response_code = try values.decodeIfPresent(String.self, forKey: .response_code)
}
现在它似乎起作用了
现在获得所需的输出[["key1": "value1", "key2": "value2"]]
评论
data
String
Reservations
response.value
switch
Result
Getdata.self
all
Test.self
Test
first_name