#ios #arrays #json #swift #dictionary
#iOS #массивы #json #swift #словарь
Вопрос:
Итак, я работал с вложенным файлом JSON (который я добавил локально в свой проект) в Swift. Я включил часть файла JSON, над которым я работаю, ниже. Данные структурированы следующим образом:
{
"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"
]
}
]
}
Для извлечения данных я создал 2 структуры, которые представляют данные в JSON, чтобы затем я мог извлекать из него значения. Это следующие:
struct Response:Codable{
let categories: [Categories]
}
struct Categories:Codable{
let categoryName : String?
let exercisesInCategory : [String]
}
Имя файла — fitnessData.json
и я пытаюсь извлечь из него данные с помощью этого кода:
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)
}
}
}
Проблема в том, что я хотел бы извлечь ВСЕ значения ‘CategoryName’ из файла JSON и ВСЕ значения ‘exercisesInCategory’. Но пока мне удалось перейти только к определенному элементу в файле JSON и получить этот элемент, т.Е.
responseJSON.categories[1].categoryName!
Я хотел бы выполнить итерацию по файлу JSON, чтобы получить все значения ‘CategoryName’, например. Однако для того, чтобы сделать это, мне пришлось бы написать что-то вроде этого:
for value in responseJSON.categories[1].categoryName! {
print(value)
}
Где ‘1’ представляет все значения для структуры categories. Приведенный выше код, очевидно, напечатает только CategoryName второго индекса в массиве categories в файле JSON. Может ли кто-нибудь указать мне правильное направление?
Ответ №1:
Вы можете сделать это следующим образом:
for category in responseJSON.categories {
print(category.categoryName!)
}
Или вы можете использовать функцию map для получения всего categoryName
подобного:
let categoryNames = responseJSON.categories.map {$0.categoryName}
Ответ №2:
Просто так.
response.categories.forEach { print($0.categoryName) }
Комментарии:
1. Спасибо за ваш вклад. Ответ кажется таким простым, все это время я пытался сделать это правильно в течение многих часов, ха-ха.
Ответ №3:
Если вы хотите поместить оба значения в разные массивы:
var categoryNameList = [String]
var excercisesInCategory = [[String]]
for category in responseJSON.categories {
categoryNameList.append(category.categoryName)
excercisesInCategory.append(category. exercisesInCategory)
}
Ответ №4:
это.
let categories = responseJSON.categories.map { $0.categoryName }
categories.forEach { print($0) }
Ответ №5:
Если вы выполняете итерацию по String
, каждый элемент представляет собой один символ строки.
Вы можете выполнять итерации по categories
массиву
for category in responseJSON.categories {
print(category.categoryName ?? "No name")
}
Чтобы получить все имена, вы можете использовать, compactMap
который удаляет nil
значения из массива
let names = responseJSON.categories.compactMap { $0.categoryName }
Далее:
-
Если у каждой категории есть свое название, сделайте тип этого свойства необязательным
String
(тогда вы можете использоватьmap
вместоcompactMap
) -
Я бы улучшил ваше именование. Переименуйте
categoryName
ключ json вname
используяCodingKeys
enum. Тогда вы могли бы сделатьcategory.name
Ответ №6:
Если вы хотели получить весь JSON-файл categoryName
и exercisesInCategory
сформировать его, то вам не нужно передавать жестко закодированный индекс. Используйте следующую модифицированную функцию, она выполнит всю работу..
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)
}
}
}