Reputation: 3282
So I've been working with a nested JSON file (that I added locally to my project) in Swift. I've included a part of the JSON file I'm working on below. The data is structured as follows:
{
"categories": [
{
"categoryName": "Albatrosses",
"exercisesInCategory": [
"Wandering albatross",
"Grey-headed albatross",
"Black-browed albatross",
"Sooty albatross",
"Light-mantled albatross"
]
},
{
"categoryName": "Cormorants",
"exercisesInCategory": [
"Antarctic shag",
"Imperial shag",
"Crozet shag"
]
},
{
"categoryName": "Diving petrels",
"exercisesInCategory": [
"South Georgia diving petrel",
"Common diving petrel"
]
},
{
"categoryName": "Ducks, geese and swans",
"exercisesInCategory": [
"Yellow-billed pintail"
]
}
]
}
In order to retrieve the data I made 2 structures that represent the data in the JSON so I can then retrieve values from it. These are as follows:
struct Response:Codable{
let categories: [Categories]
}
struct Categories:Codable{
let categoryName : String?
let exercisesInCategory : [String]
}
The file name is fitnessData.json
and I'm trying to retrieve the data from it by using this code:
private func parse(){
print("Retrieving JSON Data...")
if let url = Bundle.main.url(forResource: "fitnessData", withExtension: "json") {
do {
let data = try Data(contentsOf: url)
self.response = try JSONDecoder().decode(Response.self, from: data)
if let responseJSON = self.response {
print("The categories are: ", responseJSON.categories[1].categoryName!)
}
} catch {
print(error)
}
}
}
The problem is that I would like to retrieve ALL the 'categoryName' values from the JSON file, and ALL the 'exercisesInCategory' values. But so far I've only managed to navigate towards a specific item in the JSON file and retrieving that item i.e.
responseJSON.categories[1].categoryName!
I would like to iterate over the JSON file to get all of the 'categoryName' values for example. However in order to do that I'd have to write something like this:
for value in responseJSON.categories[1].categoryName! {
print(value)
}
Where '1' represents all the values for the categories struct. The code above will obviously print only the categoryName of the second index in the categories array in the JSON file. Could someone point me in the right direction?
Upvotes: 2
Views: 2634
Reputation: 1046
If you wanted to get all the categoryName
and exercisesInCategory
form JSON file, then you don't need to pass hard coded index. Use the following modified function, it will do the work..
private func parse(){
print("Retrieving JSON Data...")
if let url = Bundle.main.url(forResource: "fitnessData", withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let response = try JSONDecoder().decode(Response.self, from: data)
for category in response.categories {
print("Category Name: \(category.categoryName!)")
for exercises in category.exercisesInCategory {
print("Exercise in category: \(exercises)")
}
}
} catch {
print(error)
}
}
}
Upvotes: 0
Reputation: 11210
If you iterate through the String
, each item is single character of string.
You can iterate through categories
array
for category in responseJSON.categories {
print(category.categoryName ?? "No name")
}
To get all names, you can use compactMap
which removes nil
values from an array
let names = responseJSON.categories.compactMap { $0.categoryName }
Next:
If each category has its name, make type of this property non-optional String
(then you can use map
instead of compactMap
)
I would improve your naming. Rename categoryName
key of json to name
using CodingKeys
enum. Then you could do
category.name
Upvotes: 0
Reputation: 48
this.
let categories = responseJSON.categories.map { $0.categoryName }
categories.forEach { print($0) }
Upvotes: 0
Reputation: 107221
You can do that like:
for category in responseJSON.categories {
print(category.categoryName!)
}
Or you can use map function for getting all the categoryName
like:
let categoryNames = responseJSON.categories.map {$0.categoryName}
Upvotes: 4
Reputation: 6547
If you would like to put both values in different arrays:
var categoryNameList = [String]
var excercisesInCategory = [[String]]
for category in responseJSON.categories {
categoryNameList.append(category.categoryName)
excercisesInCategory.append(category. exercisesInCategory)
}
Upvotes: 0
Reputation: 5088
Simply like this.
response.categories.forEach { print($0.categoryName) }
Upvotes: 0