从JSON获取对象

时间:2019-05-22 15:06:18

标签: ios json swift

我的问题: 我使用网站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。可以。

enter image description here

接下来,我想转换数据并将其写入结构数组。

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.

我的结构可能有误。我不能解决这个问题。

3 个答案:

答案 0 :(得分:3)

两个错误。

  1. 实际错误

      

    类型'Array'不匹配:预期对Array进行解码,但找到了字典。

    表示您正在忽略根对象,即键为categories的字典

  2. 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