Извлечение и анализ JSON

#ios #json #swift #parsing #decodable

#iOS #json #swift #синтаксический анализ #декодируемый

Вопрос:

Мне очень сложно получить и проанализировать следующий JSON. Я даже не могу извлечь данные из заданного URL, а тем более проанализировать их, используя мою модель данных «Car». Любая помощь более чем приветствуется!

JSON

 {
   "cars":[
      {
         "date_stolen":1604616183,
         "description":null,
         "body_colors":[
            "Black",
            "Blue"
         ],
         "id":"944846",
         "is_stock_img":false,
         "large_img":null,
         "location_found":null,
         "manufacturer_name":"Toyota",
         "external_id":null,
         "registry_name":null,
         "registry_url":null,
         "serial":"36-17-01012-xl09",
         "status":null,
         "stolen":true,
         "stolen_location":"Calgary - CA",
         "thumb":null,
         "title":"2017 Toyota Corolla ",
         "url":"https://cars.org/944846",
         "year":2017
      }
   ]
}
  
 struct Car: Decodable {
        let cars: String
    }
  
 var cars = [Car]()
  
 fileprivate func fetchJSON() {
        let urlString = "someUrl…"
        guard let url = URL(string: urlString) else { return }
        URLSession.shared.dataTask(with: url) { (data, _, err) in
            DispatchQueue.main.async {
                if let err = err {
                    print("Failed to get data from url:", err)
                    return
                }
                
                guard let data = data else { return }
                
                do {
                    
                    let decoder = JSONDecoder()
                    
                    decoder.keyDecodingStrategy = .convertFromSnakeCase

                    print("DATA n", data)
                    self.cars = try decoder.decode(Car.self, from: data)
                    
                    print("---> ", data)
                    
                } catch let jsonErr {
                    print("Failed to decode:", jsonErr)
                }
            }
        }.resume()
    }
  

Комментарии:

1. Каковы результаты?

2. Ваша модель данных car не отражает структуру json.

3. Поскольку cars это не строка, она не будет анализироваться

4. Ваш JSON неправильно сформирован. В нем не совпадают кавычки, не совпадают символы «[» и «{«.

Ответ №1:

Ваша модель автомобиля не представляет вашу структуру json.

Вы ищете что-то вроде этого :

 struct CarsResponse: Decodable {
    let cars: [CarDTO]
}

struct CarDTO: Decodable {
    let id: String
    let isStockImg: Bool
    // And so on
}
  

Тогда просто напиши :

 let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let carResponse = try decoder.decode(CarsResponse.self, from: data)
  

Вы получите доступ к своим машинам, написав

 let cars: [CarDTO] = carResponse.cars
  

Комментарии:

1. Спасибо, приятель. Кажется, это работает. Мне пришлось заменить «self.cars = try decoder.decode (Car.self, from: data)» на «пусть data = try decoder.decode (Car.self, from: data)» из-за несоответствия типов. Нужно выяснить, как извлечь ответ сейчас.

Ответ №2:

Если вы собираетесь использовать протокол Codable, и JSONDecoder() вам нужно будет создать структуру, соответствующую формату вашего JSON. Как указывали другие в своих комментариях, ваша структура Car полностью отличается от формата данных, которые вы получаете.

Если вы просто хотите десериализовать JSON, который вы получаете, в словари, содержащие значения, вы можете вместо этого использовать JSONSerialization .

Для этого вы могли бы заменить тело вашего do блока кодом, подобным этому:

 let object = try JSONSerialization.jsonObject(with: data, options: []) 
  

Затем вам придется самостоятельно перемещаться по структуре словаря object . Это не так чисто, как создание пользовательской структуры и использование Codable, но это работает.

Обратите внимание, что в вашем JSON есть синтаксические ошибки. Вот очищенная версия:

 {"cars":
    [
        {"date_stolen":1604616183,
            "description":null,
            "body_colors":["Black","Blue"],
            "id":944846,
            "is_stock_img":false,
            "large_img":null,
            "location_found":null,
            "manufacturer_name":"Toyota",
            "external_id":null,
            "registry_name":null,
            "registry_url":null,
            "serial":"36-17-01012-xl09",
            "status":null,
            "stolen":true,
            "stolen_location":"Calgary - CA",
            "thumb":null,
            "title":"2017 Toyota Corolla ",
            "url":"https://cars.org/944846",
            "year":2017
        }
    ]
}
  

(Я добавил пробелы для удобства чтения. Это не влияет на синтаксический анализ так или иначе.)