#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
}
]
}
(Я добавил пробелы для удобства чтения. Это не влияет на синтаксический анализ так или иначе.)