I have the following JSON array that is decoded from a URL, currently I am able to parse the array to access invisible object, but how can I recreate a list array of only trialid
from the JSON.
End result should look like: [27, 33]
The following is the structure of the JSON array:
[
{
"name": "mobile",
"orderid": 1,
"trialid": 27
},
{
"name": "mobile",
"orderid": 1,
"trialid": 33
}
]
The following is the what I am currently trying - how can foreach be performed here to loop through each object:
var structure = [testStructure]()
func fetch() {
guard let url = URL(string: "test.com")
else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = "id=1".data(using: .utf8)
URLSession.shared.dataTask(with: request) { data, _, error in
guard let data = data else { return }
do {
let nav = try JSONDecoder().decode(structure, from: data)
}
catch {
print(error)
}
}.resume()
}
struct testStructure: Decodable {
let name: String?
let orderid: Int?
let trialid: Int?
}
UPDATE:
After converting into a list array, I am doing the following afterwards to initiate view controllers from Storyboards
case .success( let data):
do {
let nav = try JSONDecoder().decode([TestStructure].self, from: data)
self.viewControllers = (nav.map(\.trialid)) { "\($0)" }.map {
let selected = UIImage(named: "Tab4_Large")!
let normal = UIImage(named: "Tab4_Large")!
let controller = storyboard!.instantiateViewController(withIdentifier: $0)
controller.view.backgroundColor = UIColor.white
controller.floatingTabItem = FloatingTabItem(selectedImage: selected, normalImage: normal)
return controller
}
}
catch {print(error)}
This is to overall build up a custom navigation bar
Issue 1:
Unable to infer complex closure return type; add explicit type to disambiguate
Issue 2:
Cannot call value of non-function type '[Int?]'
CodePudding user response:
First of all please name structs and classes always with starting uppercase letter and declare the struct members non-optional if the API sends consistent data
struct TestStructure: Decodable {
let name: String
let orderid: Int
let trialid: Int
}
Second of all the decoding line doesn't compile, you have to write
let nav = try JSONDecoder().decode([TestStructure].self, from: data)
To get an array of all trialid
values just map
it
let allTrialids = nav.map(\.trialid)
Update: Take the compiler's advice and add explicit type to disambiguate
self.viewControllers = nav.map { test -> UIViewController in
let selected = UIImage(named: "Tab4_Large")!
let normal = UIImage(named: "Tab4_Large")!
let controller = storyboard!.instantiateViewController(withIdentifier: String(test.trialid))
controller.view.backgroundColor = UIColor.white
controller.floatingTabItem = FloatingTabItem(selectedImage: selected, normalImage: normal)
return controller
}
CodePudding user response:
Here is how I would make the Swift model representing your JSON object. I like to make my variables optional, so if they are not in the given JSON object array, it will not fail decoding. Depends if you have a consistent data source.
struct Element: Codable {
var name: String?
var orderid, trialid: Int?
}
To decode the above code use:
let elementList = try? JSONDecoder().decode([Element].self, from: data)
To be honest, I find it pretty tedious to create Swift models from JSON objects. I recommend you checkout QuickType. This online, free, tool will generate your Swift models from JSON objects. It works with other languages as well.
Edits: based on comments I removed TypeAlias for simplicity. I disagree that it is convoluted.