我的问题: 我使用网站API-https://www.themealdb.com/api.php。
我想获得所有产品的清单。为此,链接为https://www.themealdb.com/api/json/v1/1/categories.php
在我的代码中,我创建了一个结构:
struct Category: Decodable {
var idCategory: Int?
var strCategory: String?
var strCategoryDescription: String?
var strCategoryThumb: String?
}
然后,我尝试获取地址并获取数据。我可以将传入的数据转换为JSON。可以。
接下来,我想转换数据并将其写入结构数组。
func load(url: String, completion: @escaping (_ objects: [Category])->()) {
guard let url = URL(string: url) else { return }
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
//let json = try? JSONSerialization.jsonObject(with: data, options: [])
//print("JSONSerialization" + "\(json)")
let object = try JSONDecoder().decode([Category].self, from: data)
print("JSONDecoder" + "\(object)")
completion(object)
} catch {
print(error.localizedDescription)
}
}.resume()
}
但是在这一行中,控制台出现错误:
The data couldn’t be read because it isn’t in the correct format.
我的结构可能有误。我不能解决这个问题。
答案 0 :(得分:3)
有两个错误。
实际错误
类型'Array'不匹配:预期对Array进行解码,但找到了字典。
表示您正在忽略根对象,即键为categories
的字典
键id
的值为String
而不是Int
,请注意JSON中的双引号
将所有结构成员声明为非可选常量,因为JSON提供了字典中的所有键。并将可怕的字典键映射到更有意义的成员名称。
并在error
catch块中打印所有.localizedDescription
和从不 Decodable
。
struct Response: Decodable {
let categories: [Category]
}
struct Category: Decodable {
let id: String
let name: String
let description: String
let thumbnailURL: URL
private enum CodingKeys: String, CodingKey {
case id = "idCategory"
case name = "strCategory"
case description = "strCategoryDescription"
case thumbnailURL = "strCategoryThumb"
}
}
func load(url: String, completion: @escaping ([Category]) -> Void) {
guard let url = URL(string: url) else { return }
let session = URLSession.shared
session.dataTask(with: url) { (data, _, error) in
if let error = error { print(error); return }
do {
let response = try JSONDecoder().decode(Response.self, from: data!)
print("JSONDecoder", response)
completion(response.categories)
} catch {
print(error)
completion([])
}
}.resume()
}
答案 1 :(得分:1)
您需要两个codable
struct MyData: Codable {
var categories: [Category]?
}
还有
let object = try JSONDecoder().decode(MyData.self, from: data)
答案 2 :(得分:0)
使用包装器类,您可以获取类别。以下代码在Playground中可以正常运行:
let json = """
{
"categories": [
{"idCategory": "1"},
{"idCategory": "2"}
]
}
"""
struct CategoryHolder: Codable {
var categories: [Category]
}
struct Category: Codable {
let idCategory: String?
let strCategory: String?
let strCategoryDescription: String?
let strCategoryThumb: String?
}
let jsonData = Data(json.utf8)
let categories = try JSONDecoder().decode(CategoryHolder.self, from: jsonData).categories