【问题标题】:JSON request doesn't always return same response type (object & array) [duplicate]JSON请求并不总是返回相同的响应类型(对象和数组)[重复]
【发布时间】:2018-07-22 18:31:45
【问题描述】:

TL;DR:一个 JSON 请求有时会返回一个对象,有时会返回一个对象数组作为键,我不知道如何使用 Swift 4 正确解析它。

前言:我正在使用NextBus API 制作一个巴士服务应用程序,以提供教堂山地区巴士的巴士时刻表更新和预测。但是,我在获取公交车站的预测信息时遇到了问题(NextBus API PDF 第 13-15 页上的预测请求信息)。

问题:

停止预测的请求会返回两个键:“predictions”和“copyright”。虽然“copyright”键总是为预测请求返回一个字符串,但“predictions”键有时会返回一个对象,有时会返回一个数组,具体取决于路线上是否有两辆公共汽车。

这是用 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?
}

【问题讨论】:

  • 哎哟。 与设计不佳的 API 集成的痛苦。 predictions 应该始终是一个数组,即使它只有一个条目。也许值得一提教堂山。希望我能在 Swift 上提供帮助(不是我的专业领域)。祝你好运!
  • 感谢您的信息,现在将尝试实施。给一个键一个复数名称然后返回一个对象有多傻?
  • 好吧,那没关系(命名是计算机科学中的两个难题之一,其他是缓存失效和处理非一错误)。但应该是一致的。 :-)

标签: json swift xcode


【解决方案1】:

您必须编写一个自定义初始化程序。首先解码一个字典,如果它解码一个数组失败

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)
        }
    }
}

【讨论】:

  • 这需要对我的fetchStopPrediction 方法进行任何更改吗?
  • 不,它没有。
  • jrend,你也应该感谢 vadian。您刚刚选择了这个作为正确答案,但没有给出信用:)
  • 抱歉,对于 Stack Overflow 和围绕它的礼仪有点陌生。通过给予信用,你的意思是编辑我的问题并说 vadian 的回答解决了我的问题?如果是这样,我只是这样做了。希望够了!
  • @jrend - 不,不是那样的。当您接受答案时(在 Starsky 的评论之前),您已经做了正确的事情,不知道 Starsky 上面在说什么。更多详情here.
猜你喜欢
  • 2019-05-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 2019-11-25
  • 2016-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多