TL; DR:一个JSON请求有时返回一个对象,有时返回一个键的对象数组,但我不知道如何使用Swift 4正确解析该对象。
前言:我正在使用NextBus API制作公共汽车服务应用程序,以提供教堂山地区公共汽车的公共汽车时刻表更新和预测。但是,在获取公交车站的预测信息时遇到问题( NextBus API PDF的pp 13-15页上的预测请求信息 )。
问题:
停止预测的请求返回两个键:“预测”和“版权”。尽管“版权”键始终返回用于预测请求的字符串,但“预测”键有时会返回对象,有时会根据路线上是否有两条公交车返回数组。
这是Postman可视化的问题:
预测返回一个数组:
{ "predictions": [ { "agencyTitle": "Chapel Hill Transit", "routeTag": "N", "routeTitle": "N", "stopTitle": "Estes Park Apts - Departure", "stopTag": "estepark", "dirTitleBecauseNoPredictions": "To Family Practice Building" }, { "agencyTitle": "Chapel Hill Transit", "routeTag": "N", "routeTitle": "N", "stopTitle": "Estes Park Apts - Arrival", "stopTag": "estepark_a", "dirTitleBecauseNoPredictions": "To Family Practice Building" } ], "copyright": "All data copyright Chapel Hill Transit 2018." }
预测返回一个对象:
{ "predictions": { "agencyTitle": "Chapel Hill Transit", "routeTag": "A", "routeTitle": "A", "stopTitle": "Martin Luther King Jr Blvd at Timber Hollow", "stopTag": "airptimb_s", "dirTitleBecauseNoPredictions": "To Northside" }, "copyright": "All data copyright Chapel Hill Transit 2018." }
我正在使用Swift 4在Xcode 9.4.1中创建此应用程序。这是当前处理请求的代码:
func fetchStopPrediction(stopId: String, routeTag: String, completion: @escaping (Predictions) -> Void) { let routeInfo = "\(stopId)&routeTag=\(routeTag)" let urlString = baseUrl + routeInfo print(urlString) Alamofire.request(urlString, method: .get).responseJSON { (response) in if let jsonResponse = response.result.value { print("JSON: \(jsonResponse)") } if let data = response.data { do { let predictions = try self.decoder.decode(Predictions.self, from: data) completion(predictions) } catch let error { print("Error", error) } } } } struct Predictions: Codable { let predictions: [Prediction?] let copyright: String? }
您必须编写一个自定义初始化程序。首先解码字典,如果字典解码失败
struct Predictions : Decodable { let predictions: [Prediction] let copyright: String private enum CodingKeys: String, CodingKey { case predictions, copyright } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) copyright = try container.decode(String.self, forKey: .copyright) do { let prediction = try container.decode(Prediction.self, forKey: .predictions) predictions = [prediction] } catch DecodingError.typeMismatch { predictions = try container.decode([Prediction].self, forKey: .predictions) } } }