@RememberMeOne

Как спарить сложные данные JSON?

Доброго времени суток.
Возникла сложность в обучении с получением данных из json.
Пользуюсь стандартными методами для получения данных - Codable.
Сам json -
blackstarshop.ru/index.php?route=api/v1/categories

Как можете заметить, ключ категорий начинается с числовых значений, что не позволяет мне задать их как имена переменных.
Получил подсказку, что нужно получаемый json преобразовать к виду NSDictionary и после через цикл перебрать для вывода кол-ва категорий в TableView.
Каким образом это можно реализовать, либо можно использовать для этого какие-то сторонние библиотеки?
  • Вопрос задан
  • 223 просмотра
Решения вопроса 1
doublench21
@doublench21 Куратор тега Swift
У вас JSON кривой по ссылке. В этой строчке
{"id":67,"iconImage":"image\/catalog\/style\/modile\/icons-03.png"
id имеет целочисленный тип, хотя во всех остальных местах это строка.
5dd182bfe2d36713711596.jpeg

Если не учитывать этот косяк в JSON, то такое можно спарсить как-то так:
5dd181e2cd959773181456.png

Код
struct EntryList: Decodable {
  struct DynamicCodingKey: CodingKey {
    var stringValue: String
    init?(stringValue: String) { self.stringValue = stringValue }
    var intValue: Int? { nil }
    init?(intValue: Int) { nil }
  }

  struct Entry: Decodable {
    struct Content: Decodable {
      struct Subcategory: Decodable {
        let id: String
        let iconImage: String
        let name: String
        let sortOrder: String
        let type: String
      }
      
      let iconImage: String
      let iconImageActive: String
      let image: String
      let name: String
      let sortOrder: String
      let subcategories: [Subcategory]
    }
    
    let name: String
    let content: Content
  }
 
  let entries: [Entry]
  
  init(from decoder: Decoder) throws {
    let entriesContainer = try decoder.container(keyedBy: DynamicCodingKey.self)
    
    entries = try entriesContainer.allKeys.map { key in
      print(key)
      let content = try entriesContainer.decode(Entry.Content.self, forKey: key)
      return Entry(name: key.stringValue, content: content)
    }
  }
}

var entryList: EntryList?

let task = URLSession
  .shared
  .dataTask(with: URL(string: "https://blackstarshop.ru/index.php?route=api/v1/categories")!) { (data, _, error) in
    guard error == nil else { return }
    guard let data = data else { return }
    
    entryList = try! JSONDecoder().decode(EntryList.self, from: data)
  }

task.resume()
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Zinapp
@Zinapp
iOS Developer from Rivne, Ukraine.
Я думаю, что QuickType поможет вам в разы быстрее сориентироваться с глубоким JSON'ом, анализируя то, что там лежит. К примеру если вы, как нормальный человек в массиве из 255 объектов можете пропустить пустое поле по какому-либо ключу - это решение поможет. Если хоть один раз такова ситуация повториться - оно поставить optional вместо обычного значения. Пользуйтесь :)
5dd4681c324c5009446391.png
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы