macOS - 从Raw Github获取JSON数据并解析

3
我正在尝试从githubusercontent获取JSON(URL:https://raw.githubusercontent.com/nacrt/SkyblockClient-REPO/main/files/mods.json)并将其转换为Swift文件,然后将其转换为可操作的内容,例如使用enabled(以下)来选中/取消复选框。
问题所在的JSON实际上是一系列JSON,这是主要问题。我不确定下面的代码是否有效,因为我还没有导入JSON。
至此,我已经找到了以下内容:
struct ModsJSON: Decodable {
    let id: String
    let display: String
    let description: String
    let url: String
    let config: Bool?
    let enabled: Bool
    let hidden: Bool
    let icon: String
    let categories: Array<String>
    let actions: Array<OptionAction>?
    let warning: ActionWarning?
}

let jsonData = JSON.data(using: .utf8)! //JSON being the imported json
let mods_json: [ModsJSON] = try! JSONDecoder().decode([ModsJSON].self, from: jsonData)

我是一名Swift的初学者,我知道这应该很容易,但我无法在任何地方找到实用的答案。
macOS Big Sur - 最新的Swift和Xcode版本。
2个回答

1
对于初学者来说,这并不容易,你需要使用URLSession异步加载数据。
JSON字典中的一些键丢失了,因此你需要将更多的结构成员声明为可选的。
actionswarning的类型缺失,我将它们注释掉了,但即使没有它们,代码也可以正常工作。
struct Mod: Decodable {
    let id: String
    let display: String
    let description: String
    let url: String?
    let config: Bool?
    let enabled: Bool?
    let hidden: Bool?
    let icon: String?
    let categories: [String]?
    // let actions: Array<OptionAction>?
    // let warning: ActionWarning?
}

let url = URL(string: "https://raw.githubusercontent.com/nacrt/SkyblockClient-REPO/main/files/mods.json")!

let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
    if let error = error { print(error); return }
    do {
        let result = try JSONDecoder().decode([Mod].self, from: data!)
        print(result)
    } catch { print(error) }
}
task.resume()

你的代码中存在一些不良实践:

  • 如果可能会出现错误,不要使用try!,而是始终使用do-catch块。
  • Swift中的变量名应该是lowerCamelCase而不是snake_case
  • 不要注释编译器可以推断出的类型。
  • 在数组中使用的结构体应该以单数形式命名(Mod),而JSON后缀是无意义的。

不要对编译器可以推断的类型进行注释。我不同意这一点。通过帮助编译器推断类型,您可以大大加快编译速度。 - matt
@matt 根据我的经验,初学者通常会通过注释类型来使事情变得更糟。 - vadian

1

Vadian是正确的。数组中任何元素中不存在的内容都必须被标记为Optional:

struct ModsJSON: Decodable {
    let id: String
    let display: String
    let description: String
    let url: String?
    let config: Bool?
    let enabled: Bool?
    let hidden: Bool?
    let icon: String?
    let categories: Array<String>?
    // let actions: Array<OptionAction>?
    //let warning: ActionWarning?
}

你的代码将成功解析JSON。然后,你可以像这样学习所有enabled值。

let enableds = mods_json.map {$0.enabled}

但是其中一些元素缺少enabled属性,所以您需要决定如何处理。结果如下:

[Optional(true), Optional(true), nil, Optional(true), Optional(true), Optional(true), Optional(true), nil, nil, nil, nil, nil, nil, nil, Optional(false), nil, Optional(false), Optional(false), nil, Optional(false), Optional(false), Optional(false), nil, nil]

如何将这些数据反映到您的界面中是一个完全不同的问题!

这两个答案似乎都应该可以工作,但是当我在SwiftUI中使用它们时(我已经导入了foundation),它返回错误,说表达式不允许在顶层。我认为我需要在另一个swift文件中使用它,但我不知道如何做,或者创建一个函数,但我已经尝试过了,似乎没有什么作用。我感谢这些答案,并且想将它们标记为正确的,但到目前为止还没有成功。 我觉得我可能错过了一些非常明显的东西... - stefthedoggo4
1
但这与您实际提出的问题无关。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接