Reputation: 319
I am very new to JSON parsing and tried to parse a JSON file which has list of cars but when I do parse, it gives out 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,"=======")
}
and when I made some modifications to this code as below:
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,"=======")
}
then I get and error saying:
"Type 'Any' has no subscript members"
below is a sample of the JSON file that I am using
[{"brand": "Aston Martin", "models": ["DB11","Rapide","Vanquish","Vantage"]}]
Upvotes: 3
Views: 8220
Reputation: 2124
Please note that variable JSON
in your code is an array of objects.
You have to cast it properly.
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,"=======")
}
}
}
Upvotes: 2
Reputation: 285210
The outer object is an array, please note the []
and the value for key models
is a String array.
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,"=======")
}
}
or more comfortable with 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,"=======")
}
}
Normally you are strongly discouraged from force unwrapping optionals with !
but in this case the code must not crash because a file in the application bundle is read-only at runtime and any crash would reveal a design mistake.
Upvotes: 8
Reputation: 100543
You need
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)
}
Your problem as
let JSON = try! JSONSerialization.jsonObject(with: data, options: [])
returns Any
, so you can't use subscript it like a dictionary here JSON["brand"]
Upvotes: 7