Как разобрать данные JSON из локальных файлов? - PullRequest
0 голосов
/ 08 января 2019

Я очень новичок в разборе json и пытался разобрать файл json, в котором есть список автомобилей, но когда я выполняю разбор, он выдает nil

    func jsonTwo(){
    let url = Bundle.main.url(forResource: "car_list", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    let JSON = try! JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
    print(".........." , JSON , ".......")
    let brand = JSON?["models"] as? [[String : Any]]
    print("=======",brand,"=======")
}

и когда я сделал некоторые изменения в этом коде, как показано ниже

    func jsonTwo(){
    let url = Bundle.main.url(forResource: "car_list", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    let JSON = try! JSONSerialization.jsonObject(with: data, options: []) 
    print(".........." , JSON , ".......")
    let brand = JSON["brand"] as? [[String : Any]]
    print("=======",brand,"=======")
}

тогда я получаю сообщение об ошибке "Тип 'Любой' не имеет подписных элементов"

ниже приведен пример файла json, который я использую

[{"brand": "Aston Martin", "models": ["DB11","Rapide","Vanquish","Vantage"]}]

Ответы [ 3 ]

0 голосов
/ 08 января 2019

Вам нужно

struct Root: Codable {
    let brand: String
    let models: [String]
} 

do {

     let url = Bundle.main.url(forResource: "car_list", withExtension: "json")!
     let data = try Data(contentsOf: url) 
     let res = try JSONDecoder().decode([Root].self, from: data)
     print(res)

}
catch { 
    print(error)
}

Ваша проблема как

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

возвращает Any, поэтому вы не можете использовать его как словарь здесь JSON["brand"]

0 голосов
/ 08 января 2019

Обратите внимание, что переменная JSON в вашем коде является массивом объектов. Вы должны разыграть его правильно.

func jsonTwo(){
    let url = Bundle.main.url(forResource: "car_list", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    let JSON = try! JSONSerialization.jsonObject(with: data, options: []) 
    print(".........." , JSON , ".......")
    if let jsonArray = JSON as? [[String: Any]] {
        for item in jsonArray {
            let brand = item["brand"] as? String ?? "No Brand" //A default value
            print("=======",brand,"=======")
        }
    }
}
0 голосов
/ 08 января 2019

Внешний объект - это массив, обратите внимание на [], а значение для ключа models - это массив строк.

func jsonTwo() {
    let url = Bundle.main.url(forResource: "car_list", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    let json = try! JSONSerialization.jsonObject(with: data) as! [[String : Any]]
    print(".........." , JSON , ".......")
    for item in json {
        let brand = item["brand"] as! String
        let models = item["models"] as! [String]
        print("=======",brand, models,"=======") 
    }
}

или более комфортно с Decodable

struct Car: Decodable {
    let brand : String
    let models : [String]
}

func jsonTwo() {
    let url = Bundle.main.url(forResource: "car_list", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    let cars = try! JSONDecoder().decode([Car].self, from: data)
    for car in cars {
        let brand = car.brand
        let models = car.models
        print("=======",brand, models,"=======") 
    }
}

Обычно вам настоятельно не рекомендуется принудительное развертывание опций с !, но в этом случае код не должен аварийно завершать работу, поскольку файл в комплекте приложений доступен только для чтения во время выполнения, и при любом аварийном завершении обнаруживается дизайн * 1012. * ошибка.

...