在swift中从不同的JSON响应中获取特定值



我有一个名为College 的模型

class College : Decodable {
let name : String
let id : String
let iconUrl : String
}

以及一些与大学相关的API,每个API的响应都略有不同。是2个例子

  1. 获取api/v1/colleges此API的响应JSON为

    {"成功":一串"学院":[学院]}

  2. 获取api/v1/college/{collegeID}此API的响应JSON为

    {"成功":一串"学院":学院}

现在,从这两个回复中,我只需要获得大学信息;成功;我的问题是,如何在不为每个API创建单独的响应模型的情况下获得大学信息?目前,我已经为每个API响应实现了单独的类

class GetCollegesResponse : Decodable {
let success : String
let colleges : [College]
}

class GetCollegeResponse : Decodable {
let success : String
let college : College
}

我在各自的API调用中使用它们,比如这样的

Alamofire.request(api/v1/colleges ....).responseJSON { response in
let resp = JSONDecoder().decode(GetCollegesResponse.self, response.data)
//get colleges from resp.colleges
}

Alamofire.request(api/v1/college/(id) ....).responseJSON { response in
let resp = JSONDecoder().decode(GetCollegeResponse.self, response.data)
// get college form resp.college
}

有没有更简单的方法来完成这件事?

也许正确的方法是将响应建模为泛型类型,比如这样的:

struct APIResponse<T: Decodable> {
let success: String
let payload: T
}

您可以从中提取有效载荷。

问题是有效载荷的密钥发生了变化:单个结果为college,多个大学结果为colleges

如果你真的不在乎,只想要有效载荷,我们可以有效地忽略它,并将任何密钥(除了"成功"(解码为预期类型T:

struct APIResponse<T: Decodable> {
let success: String
let payload: T
// represents any string key
struct ResponseKey: CodingKey {
var stringValue: String
var intValue: Int? = nil
init(stringValue: String) { self.stringValue = stringValue }
init?(intValue: Int) { return nil }
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ResponseKey.self)

let sKey = container.allKeys.first(where: { $0.stringValue == "success" })
let pKey = container.allKeys.first(where: { $0.stringValue != "success" })
guard let success = sKey, let payload = pKey else {
throw DecodingError.keyNotFound(
ResponseKey(stringValue: "success|any"),
DecodingError.Context(
codingPath: container.codingPath, 
debugDescription: "Expected success and any other key"))
}
self.success = try container.decode(String.self, forKey: success)
self.payload = try container.decode(T.self, forKey: payload)
}
}

然后你可以根据预期的有效载荷进行解码:

let resp = try JSONDecoder().decode(APIResponse<[College]>.self, response.data)
let colleges = resp.payload

如果不为整个响应创建模型,恐怕无法从json响应中获取特定项的值。(至少使用可编码(

首先,我们将以编码形式(UTF8(接收从服务器发送的有效载荷。因此,在使用它之前,我们必须先对其进行解码,这就是codable帮助我们解码数据的地方。如果您希望看到使用字符串的原始转换,请尝试此方法。

let dataConvertedToString = String(data: dataReceivedFromServer, encoding: .utf8)

如果您仍然喜欢从JSON响应中单独获取值,我建议您使用SwiftyJSON。它是一个茧状的框架。您可以像这样使用SwiftyJSON。

let json = try! JSON(data: dataFromServer)
json["success"].boolValue
json["college"]["name"].stringValue

相关内容

  • 没有找到相关文章

最新更新