#ios #json #swift
#iOS #json #swift
Вопрос:
Я не знаю, как получить доступ к значению ‘duration’ в моем вложенном необязательном NSSingleObjectArrayI, который создается из ответа JSON. Как мне получить доступ к вложенным значениям в этой структуре данных?
Когда я вызываю print(firstRow[«элементы»]), я получаю следующий вывод:
Optional(<__NSSingleObjectArrayI 0x60000120f920>(
{
distance = {
text = "1.8 km";
value = 1754;
};
duration = {
text = "5 mins";
value = 271;
};
"duration_in_traffic" = {
text = "4 mins";
value = 254;
};
status = OK;
}
))
Я пробовал индексирование строк (firstRow [‘elements’] [‘duration’]), но получаю ошибки.
fetchData { (dict, error) in
if let rows = dict?["rows"] as? [[String:Any]]{
if let firstRow = rows[0] as? [String:Any]{
print("firstRow is")
print(firstRow["elements"])
// Trying to access duration within firstRow['elements'] here
}
}
}
Для справки, это функция fetchData:
func fetchData(completion: @escaping ([String:Any]?, Error?) -> Void) {
let url = getRequestURL(origin: "test", destination: "test")!;
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
if let array = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any]{
completion(array, nil)
}
} catch {
print(error)
completion(nil, error)
}
}
task.resume()
}
Пример HTTP-запроса JSON находится здесь:
https://maps.googleapis.com/maps/api/distancematrix/json?destinations=77 Massachusetts Ave, Cambridge, MAamp;departure_time=nowamp;key=AIzaSyB65D4XHv6PkqvWJ7C-cFvT1QHi9OkqGCEamp;origins=428 Memorial Dr, Cambridge, MA
Комментарии:
1. Не могли бы вы добавить оригинальный json и проанализировать код, пожалуйста? Таким образом, помочь вам будет намного проще.
2. Также не могли бы вы сначала попытаться развернуть свой массив? Например, так: firstRow [‘элементы’] [0] [‘длительность’] или firstRow [‘элементы’].first [‘длительность’]
3. Используйте Codable, а не JSONSerialization.
4. @matt Не могли бы вы, пожалуйста, уточнить? Я не очень знаком с Codable.
5. @AntonVlasov Я попробовал это и получил ноль: (
Ответ №1:
Видя ваш вывод, ваш firstRow["elements"]
необязателен, поэтому вам нужно развернуть его. И на самом деле это NSArray с одним элементом, где единственным элементом является словарь, с 4 записями — «расстояние», «длительность», «duration_in_traffic» и «статус». Возможно, вам потребуется преобразовать элемент в словарь, чтобы получить доступ к каждой записи.
Для этой цели вы можете использовать необязательную привязку с as?
-приведением:
fetchData { (dict, error) in
if let rows = dict?["rows"] as? [[String: Any]] {
if let firstRow = rows.first {
print("firstRow is")
print(firstRow["elements"])
//Unwrap and cast `firstRow["elements"]`.
if let elements = firstRow["elements"] as? [[String: Any]] {
//The value for "duration" is a Dictionary, you need to cast it again.
if let duration = elements.first?["duration"] as? [String: Any] {
print(duration["text"] as? String)
print(duration["value"] as? Int)
}
}
}
}
}
Или слишком глубоко вложенные if
s трудно читать, поэтому кому-то это понравится как:
fetchData { (dict, error) in
if
let rows = dict?["rows"] as? [[String: Any]],
let firstRow = rows.first,
let elements = firstRow["elements"] as? [[String: Any]],
let duration = elements.first?["duration"] as? [String: Any]
{
print(duration["text"] as? String)
print(duration["value"] as? Int)
}
}
Или использование guard
может быть лучшим решением.
Или же, если вы можете показать нам весь текст JSON в удобочитаемом формате, кто-нибудь покажет вам, как использовать Codable, который является современным способом работы с JSON в Swift.
Комментарии:
1. Спасибо! Я очень легко внедрил Codeable и получил свои кодируемые классы через swiftjson.com
2. @Willy, кажется, ты нашел симпатичный сайт для работы
Codable
. Удачного кодирования.