我正在尝试解码以下json:
[
{
"breeds":[
{
"weight":{
"imperial":"65 - 75",
"metric":"29 - 34"
},
"height":{
"imperial":"21 - 28",
"metric":"53 - 71"
},
"id":14,
"name":"American Foxhound",
"country_code":"US",
"bred_for":"Fox hunting, scent hound",
"breed_group":"Hound",
"life_span":"8 - 15 years",
"temperament":"Kind, Sweet-Tempered, Loyal, Independent, Intelligent, Loving"
}
],
"id":"p4xvDeEpW",
"url":"https://cdn2.thedogapi.com/images/p4xvDeEpW.jpg",
"width":680,
"height":453
}
]
我的模型设置为:
struct Request: Decodable {
let response: [Response]
}
struct Response: Decodable {
let breeds: [Dog]
let url: String
}
struct Dog: Decodable {
let weight: Measurement
let height: Measurement
let name: String
let countryCode: String?
let breedGroup: String
let lifeSpan: String
let temperament: String
let origin: String?
}
struct Measurement: Decodable {
let imperial: String
let metric: String
}
我按如下方式调用API:
func fetchDogs(with request: URLRequest, completion: @escaping (([Dog]?, String?, Error?) -> ())) {
URLSession.shared.dataTask(with: request) { (data, response, error) in
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
guard let data = data,
let request = try? decoder.decode(Request.self, from: data) else {
completion(nil, nil, error)
return
}
completion(request.response[0].breeds, request.response[0].url, nil)
}.resume()
}
但是它总是命中警戒completion(nil, nil, error)
行,我不确定为什么我不确定如何将JSON的前几行分开。使用:
struct Request: Decodable {
let response: [Response]
}
似乎不正确。如果我更新了对Response
结构进行解码的请求,它仍然会引起警惕。
我的请求构建器如下:
struct RequestBuilder {
private let baseURLString: String
static var defaultBuilder: RequestBuilder {
return RequestBuilder(
baseURLString: Constant.URL.dogsBase
)
}
func dogsRequest() -> URLRequest {
return dogRequest(path: Constant.Path.search)
}
private func dogRequest(path: String) -> URLRequest {
guard var components = URLComponents(string: baseURLString) else {
preconditionFailure(Constant.PreconditionFailure.baseURL)
}
components.path = path
guard let url = components.url else {
preconditionFailure(Constant.PreconditionFailure.baseURL)
}
var request = URLRequest(url: url)
request.setValue(Constant.Key.dogs, forHTTPHeaderField: "x-api-key")
return request
}
}
可以找到here
答案 0 :(得分:2)
问题在于,当您将Request.self
传递给decode.decode
时,JSONDecoder
期望找到一个Dictionary
,其密钥为response
,这是由于您声明了{ {1}}。
您只需要将Request
传递给[Response].self
方法。
decode
如果您没有使用guard let data = data,
let request = try? decoder.decode([Response].self, from: data) else {
completion(nil, nil, error)
return
}
掩盖解码错误,则会从错误消息中立即看到问题:
typeMismatch(Swift.Dictionary,Swift.DecodingError.Context(codingPath:[],debugDescription:“预期用于解码Dictionary,但找到一个数组。”,底层错误:无))
在不确定代码是否可以正常工作时,应该始终在try?
块中使用普通的try
语句,因为这样实际上可以看到错误消息。 do-catch
会引发非常有用的错误,因此建议您不要使用JSONDecoder
将它们掩盖到nil
中。