Swift - 根据 json 响应是否包含某个键来过滤它

发布于 2025-01-12 22:13:09 字数 1393 浏览 1 评论 0原文

我想知道是否可以根据数组中的项目是否包含某个键来过滤 API 请求的响应。

我想过滤数组,以便只有包含 ["section": "name", "balls": 0, "bananas": 0] 且具有 [ "section_group": "group", "balls": 0, "bananas": 0] 实例已删除。

我该如何在 Swift 中做到这一点?

我想我应该先对 data 进行一些处理,然后再在这里对其进行解码

let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
    if (error != nil) {
        print(error!)
    } else {
        if let data = data {
            do {
                let response = try JSONDecoder().decode(Response.self, from: data)
                recipes = response.results
            }
            catch {
                print(error)
            }
        }
    }
})

结构:

struct Response: Decodable, Encodable {
    let results: [Data]
}

struct Data: Decodable, Hashable, Encodable {
    let name: String
    let thumbnail_url: String
    let sections: [Section]
    let instructions: [Instruction]
    let num_servings: Int
    let prep_time_minutes: Int?
    let cook_time_minutes: Int?
    let total_time_minutes: Int?
}

struct Section: Decodable, Hashable, Encodable {
    let components: [Ingredient]
}

struct Ingredient: Decodable, Hashable, Encodable {
    let raw_text: String
}

struct Instruction: Decodable, Hashable, Encodable {
    let display_text: String
}

I am wondering if I can filter a response from an API request based on if an item in the array contains a certain key.

I want to filter the array so that I only have instances of dictionaries that contain ["section": "name", "balls": 0, "bananas": 0] and have ["section_group": "group", "balls": 0, "bananas": 0] instances removed.

How would I do that in Swift?

I guess I should do something to data before I decode it here

let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
    if (error != nil) {
        print(error!)
    } else {
        if let data = data {
            do {
                let response = try JSONDecoder().decode(Response.self, from: data)
                recipes = response.results
            }
            catch {
                print(error)
            }
        }
    }
})

Structs:

struct Response: Decodable, Encodable {
    let results: [Data]
}

struct Data: Decodable, Hashable, Encodable {
    let name: String
    let thumbnail_url: String
    let sections: [Section]
    let instructions: [Instruction]
    let num_servings: Int
    let prep_time_minutes: Int?
    let cook_time_minutes: Int?
    let total_time_minutes: Int?
}

struct Section: Decodable, Hashable, Encodable {
    let components: [Ingredient]
}

struct Ingredient: Decodable, Hashable, Encodable {
    let raw_text: String
}

struct Instruction: Decodable, Hashable, Encodable {
    let display_text: String
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

纵山崖 2025-01-19 22:13:09

您可以按如下方式过滤字典数组:

let desired_results = all.filter{$0.keys.contains("sections")}

其中 all[String: Any] 字典数组。

闭包返回一个布尔值,如果字典的键包含“sections”,则返回 true。

有关过滤器的更多信息: https://developer.apple.com/documentation/swift/ sequence/3018365-filter

编辑:如果你想过滤 Response.results 只包含 50 个键的对象,你可以忽略那些无法解码的对象如下:

struct Response: Decodable, Encodable {
    let results: [String]
}

我将您的 Data 重命名为 Recipe 因为 Data 已经是一种类型,您应该使用不同的名称。

let response = try JSONDecoder().decode(Response.self, from: data)

recipes = response.results.compactMap({
    do {
        return try JSONDecoder().decode(Recipe.self, from: Data($0))
    } catch {
        return nil
    }
})

CompactMap 忽略 nil 值,这些值是 JSONDecoder 无法解码的值(对象)。这样你就有了一个Recipe数组

You can filter an array of dictionaries as follows:

let desired_results = all.filter{$0.keys.contains("sections")}

where all is your array of [String: Any] dictionaries.

The closure returns a boolean, true if the keys of the dictionary contain "sections".

More about filter: https://developer.apple.com/documentation/swift/sequence/3018365-filter

edit: If you want to filter Response.results to only include the 50-key objects, you can ignore ones that fail to be decoded as follows:

struct Response: Decodable, Encodable {
    let results: [String]
}

I renamed your Data to Recipe because Data is already a type, and you should use a different name.

let response = try JSONDecoder().decode(Response.self, from: data)

recipes = response.results.compactMap({
    do {
        return try JSONDecoder().decode(Recipe.self, from: Data($0))
    } catch {
        return nil
    }
})

compactMap ignores the nil values, which are the ones where JSONDecoder fails to decode (the objects). This way you have an array of Recipe

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文