Reputation: 305
I've been trying for hours to read values from a JSON file in the app bundle and print those values. I've been scouring several forums and SO questions trying to piece together a way to read from a .json file, but have had no luck. What I currently have is a bunch of (probably useless) code that looks like this:
//json parsing
if let path = Bundle.main.path(forResource: "POIs", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
if let jsonResult = jsonResult as? Dictionary<String, AnyObject>, let pois = jsonResult["POI"] {
print("test ", pois)
for poi in pois as! [AnyObject] {
guard let name = poi["name"], //String
let coordinatesJSON = poi["coordinates"] as? [String: Double],
let latitudeVar = coordinatesJSON["lat"],
let longitudeVar = coordinatesJSON["lng"],
let altitude = poi["altitude"], //Int
let facebookurl = poi["facebookurl"], //String
let poiImage = poi["pinImage"] //String
else {
return
}
and my POIs.json file looks like this:
{
"POI":[
{
"name": "Boston Paintball",
"coordinates": {
"lat": 42.401848,
"lng": -71.023843
},
"altitude": 7,
"facebookurl": "https://www.facebook.com/PlayBostonPaintball/",
"pinImage": "bp"
},
{
"name": "Chilis",
"coordinates": {
"lat": 42.402314,
"lng": -71.021655
},
"altitude": 7,
"facebookurl": "https://www.facebook.com/chilis",
"pinImage": "chilis"
}
]
}
Can anyone show me the best way to read values from a json, store them into the variables I specified, and then print them? Thank you!
UPDATED CODE:
//json parsing
let file = Bundle.main.url(forResource: "POIs", withExtension: "json")
let data = try? Data(contentsOf: file!)
let root = try? JSONDecoder().decode(Root.self, from: data!)
do {
let root = try JSONDecoder().decode(Root.self, from: data!)
print(root)
} catch {
print(error)
}
let decoder = JSONDecoder()
let pois = try? decoder.decode([Root].self, from: data!)
let pinUIImage = UIImage(named: Location.pinImage)
But still giving me a Instance member 'pinImage' cannot be used on type 'ViewController.Location'
error.
UPDATE 2:
for poi in (root?.pointsOfInterest)! {
if let location = root?.pointsOfInterest.??? { //I dont know how to grab the poi from the current iteration. Any tips?
Upvotes: 1
Views: 226
Reputation: 236370
You should structure your data to conform to Codable protocol:
struct Root: Codable {
let pointsOfInterest: [Location]
private enum CodingKeys: String, CodingKey {
case pointsOfInterest = "POI"
}
}
struct Location: Codable {
let name: String
let coordinates: Coordinate
let altitude: Int
let facebookurl: String
let pinImage: String
}
struct Coordinate: Codable {
let latitude: Double
let longitude: Double
private enum CodingKeys: String, CodingKey {
case latitude = "lat", longitude = "lng"
}
}
do {
let root = try JSONDecoder().decode(Root.self, from: jsonData)
print(root)
} catch {
print(error)
}
This will print
Root(pointsOfInterest: [__lldb_expr_39.Location(name: "Boston Paintball", coordinates: __lldb_expr_39.Coordinate(latitude: 42.401848000000001, longitude: -71.023842999999999), altitude: 7, facebookurl: "https://www.facebook.com/PlayBostonPaintball/", pinImage: "bp"), __lldb_expr_39.Location(name: "Chilis", coordinates: __lldb_expr_39.Coordinate(latitude: 42.402313999999997, longitude: -71.021654999999996), altitude: 7, facebookurl: "https://www.facebook.com/chilis", pinImage: "chilis")])
Upvotes: 1