swift - Swift 4 解析嵌套的 JSON 数组,这是来自 Web 服务的响应
问题描述
这是我的 JSON,它是来自 Web 服务的响应,
{
"Data": [
{
"Id": 181670,
"PatientId": 10086,
"Form": "{\"Day\":\"14-11-2019\",\"Hour\":\"08:31\"}",
"Type": 8,
"Time": "2019-11-14T08:31:00"
}
],
"Success": true,
"ErrorMessage": null
}
这是我希望将其保存到的结构
struct Response: Decodable{
let ErrorMessage: String?
let Success: Bool
var data: [Data]
enum CodingKeys: String, CodingKey {
case data = "Data"
case Success, ErrorMessage
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.data= try container.decode([Datas].self, forKey: .data)
self.Success = try container.decode(Bool.self, forKey: .Success)
self.ErrorMessage = try container.decode(String?.self, forKey: .ErrorMessage)
}
struct Data: Decodable{
let `Type`: Int
let Id, PatientId : Int64
let Form,Time: String
enum CodingKeys: String, CodingKey {
case Id, PatientId, Form,`Type`,Time
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.PatientId = try container.decode(Int64.self, forKey: .PatientId)
self.Id = try container.decode(Int64.self, forKey: .Id)
self.Form = try container.decode(String.self, forKey: .Form)
self.Time = try container.decode(String.self, forKey: .Time)
self.`Type` = try container.decode(Int.self, forKey: .`Type`)
}
}
}
然后您可以使用以下方法解码 JSON:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let response = try decoder.decode(Response.self, from: data)
print(response.data)
我使用此方法时的输出如下:
[]
我查看了 Apple 关于解码嵌套结构的文档,但我仍然不明白如何正确执行不同级别的 JSON。
---我解决这个问题的另一种方法:
let task = URLSession.shared.dataTask(with: request as URLRequest)
{(data,response,error) -> Void in
if error != nil
{
print(error?.localizedDescription as Any)
return
}
do
{
guard error == nil else {
return
}
guard let data = data else {
return
}
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary {
print(json)
if let success = json["Success"] as? Bool {
self.sucBool = success as! Bool
if let array: NSArray = json["Data"]! as? NSArray{
for obj in array {
if let dict = obj as? NSDictionary {
// Now reference the data you need using:
let form= dict.value(forKey: "Form")
}
}
}
}
}
completionHandler(self.sucBool,nil)
}
catch let error as NSError
{
print(error.localizedDescription)
completionHandler(false,error)
}
}
task.resume()
我使用此方法时的输出如下:
{
Data = (
);
ErrorMessage = "<null>";
Success = 1;
}
我可以正确读取 Web 服务响应,但对于 Data.casting 是错误的。我觉得这行代码关于强制转换有问题:
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary
---此外,两种方法都不会写入错误消息。
解决方案
- 正如@Yvonne Aburrow 提到的那样,在 JSONlint.com 上检查您的 JSON
- 重构你的结构。您可以更轻松地编写它们!例子:
struct SomeRoot: Decodable {
let data: [Data]
let success: Bool
let errorMessage: String?
}
struct Data: Decodable {
let id: Int
let patientId: Int
let form: String
let type: Int
let time: String
}
do {
let myFetchedJSON = try JSONDecoder().decode(SomeRoot.self, from: jsonObject!)
print(myFetchedJSON.data)
} catch {
print(error.localizedDescription)
}
...一些提示:
- 对于解码 json,
Decodable
协议就足够了。您使用的Codable
协议用于编码和解码。 - 你需要
do/catch
尝试JSONDecoder().deco[...]
块。如果您在catch {}
块中打印错误,您会发现出了什么问题
推荐阅读
- python - pandas.Dataframe 的列名和类型用 mypy 还是其他静态方式?
- r - 如何循环遍历 r 中多个数据帧中的多个列?
- python - 如何以一定的精度处理python浮点数
- sql - 显示一列的总量
- r - 根据输入数据为 geom_segment 设置变量位置
- jupyter-notebook - 在 Jupyter Notebook 中显示特殊字符
- javascript - 在 React Native 中获取 Firebase 云消息传递令牌
- r - 将 R_markdown 编织为 PDF 时加载命名空间出错
- c++ - 当 T==void 时如何最好地解决“void foo(const T& t = T())”
- python - 如何将定性数据转换为定量数据