I am trying to get json from a githubusercontent (URL: https://raw.githubusercontent.com/nacrt/SkyblockClient-REPO/main/files/mods.json) into a Swift file then converting it into something that I can manipulate, for example, using enabled (below) to have a checkbox checked/unchecked.
The JSON in question is actually an array of JSONs, and this is the main problem. I'm not sure if the code below will work, because I haven't imported the JSON.
So far, I've found this:
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)
I am a beginner in swift, and I realize that this should be easy, but I can't find a practical answer anywhere.
macOS Big Sur - Latest Swift and Xcode versions.
It's not that easy for a beginner, you have to load the data asynchronously with URLSession.
Some of the keys in the JSON dictionaries are missing, therefore you have to declare more struct members as optional.
The types for the keys actions and warning are missing, I commented them out, the code works without them, too
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()
There are some bad practices in your code:
try! use always a do - catch block if an error could occur.lowerCamelCase rather than snake_case.Mod) and the JSON suffix is pointless.Vadian is correct. Whatever is not present in any of the elements of the array must be marked 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?
}
Your code will then successfully parse the JSON. You can then, as you say, learn all the enabled values by saying eg.
let enableds = mods_json.map {$0.enabled}
But some of the elements lack the enabled so you would have to decide how to deal with that. The results appear as
[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]
How to reflect this data into your interface is a totally different problem!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With