提取和解析JSON

问题描述

我很难抓取并解析以下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()
    }

解决方法

您的汽车模型不代表您的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
,

如果要使用Codable协议和JSONDecoder(),则需要创建一个与JSON格式匹配的Struct。正如其他人在评论中指出的那样,您的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
        }
    ]
}

(我添加了空格以提高可读性。它不会影响一种或另一种方式的解析。)