使用 Google 从 JSON 数据创建对象 在 Swift 中放置 API
Creating Objects from JSON data using Google Places API in Swift
所以我正在创建一个应用程序,它使用 Google 地点 API 来收集餐馆列表。使用 API 为我提供了一个 JSON 文件,其中包含每个位置的详细信息,如纬度、经度、评级、priceLevel、openNow、照片等。下面是用于收集所述 JSON 从我给定的参数:
func performGoogleSearch(radius: Double, type: String, price: Int ) {
let location = locationManager.location?.coordinate
let url: URL = URL(string: "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(location?.latitude ?? 0),\(location?.longitude ?? 0)&radius=\(radius * 1609.34)&type=restaurant&maxprice=\(price)&key=AIzaSyBF0uwjr6BZc-Y-0kPsMBq2zNkl5EArioQ")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
print(NSString(data: data!, encoding: String.Encoding.utf8.rawValue))
}
task.resume()
}
返回的数据是 JSON 如下所示:
{
"html_attributions" : [],
"results" : [
{
"geometry" : {
"location" : {
"lat" : 37.7867167,
"lng" : -122.4111737
},
"viewport" : {
"northeast" : {
"lat" : 37.7881962302915,
"lng" : -122.4098846697085
},
"southwest" : {
"lat" : 37.7854982697085,
"lng" : -122.4125826302915
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"id" : "3344890deedcb97b1c2d64814f92a02510ba39c8",
"name" : "Clift San Francisco",
"opening_hours" : {
"open_now" : false,
"weekday_text" : []
},
"photos" : [
{
"height" : 900,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114937580614387417622/photos\"\u003eClift San Francisco\u003c/a\u003e"
],
"photo_reference" : "CmRaAAAAwpWxfFJMJnK8G-LWJehCyUH5PFtepMF26XkZnXDRDo0wJMe-dAXLZ0zXGDmoEMi9n8YF5rYhgnr-EoDZFUawtiITYYocTJDAAjo1hw0sos4wVpfnx186o6pPgQWEv1f0EhDrydRti0bHEkhY4FNANV_KGhRmH8m7e6mO1sR2FlFxFuo5oSl00g",
"width" : 1155
}
],
"place_id" : "ChIJFUBxSY6AhYARwOaLV7TsLjw",
"price_level" : 4,
"rating" : 4.1,
"reference" : "CmRRAAAAA4IUvt3mHf2_QejiFA1acdgH2pg5h1_6GYDuVt-bzSwHqieSXmCAye5FRGJ0EjIM03WICU82MuKOiHor65j-e8rCDNEkltQnpoUX4AbCfRdybuqIPS5FxNsV_905or7BEhDNu3bKvzktrh2USu0zSNtoGhSkqf9WV1snRVufZ11kN6YgF961YQ",
"scope" : "GOOGLE",
"types" : [
"night_club",
"bar",
"lodging",
"restaurant",
"food",
"point_of_interest",
"establishment"
],
"vicinity" : "495 Geary Street, San Francisco"
},
{
"geometry" : {
"location" : {
"lat" : 37.78988329999999,
"lng" : -122.4091511
},
"viewport" : {
"northeast" : {
"lat" : 37.79135163029149,
"lng" : -122.4078268197085
},
"southwest" : {
"lat" : 37.78865366970849,
"lng" : -122.4105247802915
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"id" : "547ceb15210b70b8734500183410bb10c644c395",
"name" : "Cornell Hotel De France",
"opening_hours" : {
"open_now" : true,
"weekday_text" : []
},
"photos" : [
{
"height" : 315,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114711934191765864568/photos\"\u003eCornell Hotel De France\u003c/a\u003e"
],
"photo_reference" : "CmRaAAAAJ3kTtFbeGT-8NWKbf9TPlN6gL6daO5zKq9DNZnzShZ-CcPUJnxMaVZybHZ0sGefM72WV01VcXr1AJWNKOSifZ63DIxxutKJ0ecqPUkM73LZLM-LO_eqsaWBRH8QN6PLYEhDykcPC3JAyDEDWpdiu3FP8GhRiJrTRNpnYQi1DDztzCRVKAM4N_A",
"width" : 851
}
],
"place_id" : "ChIJs6F3JYyAhYARDiVdBrmivCs",
"price_level" : 4,
"rating" : 4.2,
"reference" : "CmRRAAAAK05VMbTrE3cDxZreuM-Z0rbXcfdT4nflU0D17oCIwaF2RVbF85ch-1qKfRAGtMPxuuBvzw9sO-Y1rwRin-fEmzvgtiPsy8X_R2kfzh7rHX8iS8gJKc1QyTk2H4XU2O4hEhDMcIcjK5fWFvnGrJWxHgC6GhQAOkKXMCm7IjhOeOD__ZqzFlosmg",
"scope" : "GOOGLE",
"types" : [
"clothing_store",
"store",
"lodging",
"restaurant",
"food",
"point_of_interest",
"establishment"
],
"vicinity" : "715 Bush Street, San Francisco"
}
],
"status" : "OK"
}
我有一个对象叫"Location",希望把JSON作为一个参数来填充它各自的值。我想达到这样的程度,即我可以将此 JSON 转换为我的 "Location" 结构的数组,并为 [=33= 中返回的每个餐厅填充一个 "Location" ] 放置 API JSON。
这是 "Location" 结构:
import Foundation
struct Location: Codable {
var lat: Double
var long: Double
var icon: String?
var id: String?
var name: String
var openNow: Bool?
var photos: [String : Any]?
var placeID: String?
var priceLevel: Int?
var rating: Double?
var types: [String]?
init?(json: [String: Any]) {
guard let lat = json["lat"] as? Double,
let long = json["lng"] as? Double,
let icon = json["icon"] as? String,
let id = json["id"] as? String,
let name = json["name"] as? String,
let openNow = json["open_now"] as? Bool,
let photos = json["photos"] as? [String : Any],
let placeID = json ["place_id"] as? String,
let priceLevel = json["price_level"] as? Int,
let rating = json["rating"] as? Double,
let types = json["types"] as? [String]? else {
return nil
}
self.lat = lat
self.long = long
self.icon = icon
self.id = id
self.name = name
self.openNow = openNow
self.photos = photos
self.placeID = placeID
self.priceLevel = priceLevel
self.rating = rating
self.types = types
}
}
这个结构是一个开始,但显然缺乏,因为我不知道如何从 JSON 中获取数据来制作这个 "Location" 结构的数组。任何指导将不胜感激。
您可以使用JSONDecoder
let decoder = JSONDecoder()
do {
let locations = try decoder.decode([Location].self, from: yourJson)
print(locations)
} catch {
print(error.localizedDescription)
}
您还可以嵌套结构来表示您可能必须要做的数据。在 this guide to JSON parsing
上查看 "More Complex Nested Response"
我最终将 "Location" 结构更改为
- 不可编码
- 将每个 属性 作为参数而不是将整个 JSON 字典作为参数
在 "performGoogleSearch()" 函数中,我基本上必须不断将字典的值转换为字典本身,以便更深入地研究文件。然后我使用我可以从 JSON 文件中得到的每个值,并使用它们创建我的 class 的对象。然后我将每个对象附加到我的结果数组中。
func performGoogleSearch(radius: Double, type: String, price: Int ) {
let location = locationManager.location?.coordinate
let url: URL = URL(string: "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(location?.latitude ?? 0),\(location?.longitude ?? 0)&radius=\(radius * 1609.34)&type=restaurant&maxprice=\(price)&key=AIzaSyBF0uwjr6BZc-Y-0kPsMBq2zNkl5EArioQ")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
let jsonObject = try? JSONSerialization.jsonObject(with: data! as Data, options: [])
if let jsonArray = jsonObject as? [String: Any] {
if let results = jsonArray["results"] as! [Any]?{
for result in results {
if let locationDictionary = result as? [String : Any] {
let geometry = locationDictionary["geometry"]! as! [String : Any]
let location = geometry["location"]! as! [String : Any]
let lat = location["lat"]
let long = location["lng"]
let openingHours = locationDictionary["opening_hours"] as? [String : Any]
let openNow = openingHours?["open_now"]
let photos = locationDictionary["photos"] as? [[String : Any]]
let newLocation = Location(lat: lat as! Double, long: long as! Double, id: locationDictionary["id"] as? String, name: locationDictionary["name"] as! String, openNow: openNow as? Int, photos: photos, placeID: locationDictionary["place_id"] as? String, priceLevel: locationDictionary["price_level"] as? Int, rating: locationDictionary["rating"] as? Double, types: locationDictionary["types"] as? [String])
googleResults.append(newLocation!)
}
}
print("Results: \(googleResults.count)")
let randomInt = Int(arc4random_uniform(UInt32(googleResults.count)))
print("RandomInt: \(randomInt)")
if googleResults.count != 0 {
self.googleResult = googleResults[randomInt]
self.annotation = MapBoxAnnotation(coordinate: CLLocationCoordinate2D(latitude: (self.self.googleResult?.lat)!, longitude: (self.self.googleResult?.long)!), title: self.googleResult?.name, subtitle: nil)
}
}
}
DispatchQueue.main.async {
self.animateResultView()
}
}
task.resume()
位置结构:
struct Location {
var lat: Double
var long: Double
var id: String?
var name: String
var openNow: Int?
var photos: [[String : Any]]?
var placeID: String?
var priceLevel: Int?
var rating: Double?
var types: [String]?
init?(lat: Double, long: Double, id: String?, name: String, openNow: Int?, photos: [[String : Any]]?, placeID: String?, priceLevel: Int?, rating: Double?, types: [String]?) {
self.lat = lat
self.long = long
self.id = id
self.name = name
self.openNow = openNow
self.photos = photos
self.placeID = placeID
self.priceLevel = priceLevel
self.rating = rating
self.types = types
}
}
所以我正在创建一个应用程序,它使用 Google 地点 API 来收集餐馆列表。使用 API 为我提供了一个 JSON 文件,其中包含每个位置的详细信息,如纬度、经度、评级、priceLevel、openNow、照片等。下面是用于收集所述 JSON 从我给定的参数:
func performGoogleSearch(radius: Double, type: String, price: Int ) {
let location = locationManager.location?.coordinate
let url: URL = URL(string: "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(location?.latitude ?? 0),\(location?.longitude ?? 0)&radius=\(radius * 1609.34)&type=restaurant&maxprice=\(price)&key=AIzaSyBF0uwjr6BZc-Y-0kPsMBq2zNkl5EArioQ")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
print(NSString(data: data!, encoding: String.Encoding.utf8.rawValue))
}
task.resume()
}
返回的数据是 JSON 如下所示:
{
"html_attributions" : [],
"results" : [
{
"geometry" : {
"location" : {
"lat" : 37.7867167,
"lng" : -122.4111737
},
"viewport" : {
"northeast" : {
"lat" : 37.7881962302915,
"lng" : -122.4098846697085
},
"southwest" : {
"lat" : 37.7854982697085,
"lng" : -122.4125826302915
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"id" : "3344890deedcb97b1c2d64814f92a02510ba39c8",
"name" : "Clift San Francisco",
"opening_hours" : {
"open_now" : false,
"weekday_text" : []
},
"photos" : [
{
"height" : 900,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114937580614387417622/photos\"\u003eClift San Francisco\u003c/a\u003e"
],
"photo_reference" : "CmRaAAAAwpWxfFJMJnK8G-LWJehCyUH5PFtepMF26XkZnXDRDo0wJMe-dAXLZ0zXGDmoEMi9n8YF5rYhgnr-EoDZFUawtiITYYocTJDAAjo1hw0sos4wVpfnx186o6pPgQWEv1f0EhDrydRti0bHEkhY4FNANV_KGhRmH8m7e6mO1sR2FlFxFuo5oSl00g",
"width" : 1155
}
],
"place_id" : "ChIJFUBxSY6AhYARwOaLV7TsLjw",
"price_level" : 4,
"rating" : 4.1,
"reference" : "CmRRAAAAA4IUvt3mHf2_QejiFA1acdgH2pg5h1_6GYDuVt-bzSwHqieSXmCAye5FRGJ0EjIM03WICU82MuKOiHor65j-e8rCDNEkltQnpoUX4AbCfRdybuqIPS5FxNsV_905or7BEhDNu3bKvzktrh2USu0zSNtoGhSkqf9WV1snRVufZ11kN6YgF961YQ",
"scope" : "GOOGLE",
"types" : [
"night_club",
"bar",
"lodging",
"restaurant",
"food",
"point_of_interest",
"establishment"
],
"vicinity" : "495 Geary Street, San Francisco"
},
{
"geometry" : {
"location" : {
"lat" : 37.78988329999999,
"lng" : -122.4091511
},
"viewport" : {
"northeast" : {
"lat" : 37.79135163029149,
"lng" : -122.4078268197085
},
"southwest" : {
"lat" : 37.78865366970849,
"lng" : -122.4105247802915
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"id" : "547ceb15210b70b8734500183410bb10c644c395",
"name" : "Cornell Hotel De France",
"opening_hours" : {
"open_now" : true,
"weekday_text" : []
},
"photos" : [
{
"height" : 315,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114711934191765864568/photos\"\u003eCornell Hotel De France\u003c/a\u003e"
],
"photo_reference" : "CmRaAAAAJ3kTtFbeGT-8NWKbf9TPlN6gL6daO5zKq9DNZnzShZ-CcPUJnxMaVZybHZ0sGefM72WV01VcXr1AJWNKOSifZ63DIxxutKJ0ecqPUkM73LZLM-LO_eqsaWBRH8QN6PLYEhDykcPC3JAyDEDWpdiu3FP8GhRiJrTRNpnYQi1DDztzCRVKAM4N_A",
"width" : 851
}
],
"place_id" : "ChIJs6F3JYyAhYARDiVdBrmivCs",
"price_level" : 4,
"rating" : 4.2,
"reference" : "CmRRAAAAK05VMbTrE3cDxZreuM-Z0rbXcfdT4nflU0D17oCIwaF2RVbF85ch-1qKfRAGtMPxuuBvzw9sO-Y1rwRin-fEmzvgtiPsy8X_R2kfzh7rHX8iS8gJKc1QyTk2H4XU2O4hEhDMcIcjK5fWFvnGrJWxHgC6GhQAOkKXMCm7IjhOeOD__ZqzFlosmg",
"scope" : "GOOGLE",
"types" : [
"clothing_store",
"store",
"lodging",
"restaurant",
"food",
"point_of_interest",
"establishment"
],
"vicinity" : "715 Bush Street, San Francisco"
}
],
"status" : "OK"
}
我有一个对象叫"Location",希望把JSON作为一个参数来填充它各自的值。我想达到这样的程度,即我可以将此 JSON 转换为我的 "Location" 结构的数组,并为 [=33= 中返回的每个餐厅填充一个 "Location" ] 放置 API JSON。 这是 "Location" 结构:
import Foundation
struct Location: Codable {
var lat: Double
var long: Double
var icon: String?
var id: String?
var name: String
var openNow: Bool?
var photos: [String : Any]?
var placeID: String?
var priceLevel: Int?
var rating: Double?
var types: [String]?
init?(json: [String: Any]) {
guard let lat = json["lat"] as? Double,
let long = json["lng"] as? Double,
let icon = json["icon"] as? String,
let id = json["id"] as? String,
let name = json["name"] as? String,
let openNow = json["open_now"] as? Bool,
let photos = json["photos"] as? [String : Any],
let placeID = json ["place_id"] as? String,
let priceLevel = json["price_level"] as? Int,
let rating = json["rating"] as? Double,
let types = json["types"] as? [String]? else {
return nil
}
self.lat = lat
self.long = long
self.icon = icon
self.id = id
self.name = name
self.openNow = openNow
self.photos = photos
self.placeID = placeID
self.priceLevel = priceLevel
self.rating = rating
self.types = types
}
}
这个结构是一个开始,但显然缺乏,因为我不知道如何从 JSON 中获取数据来制作这个 "Location" 结构的数组。任何指导将不胜感激。
您可以使用JSONDecoder
let decoder = JSONDecoder()
do {
let locations = try decoder.decode([Location].self, from: yourJson)
print(locations)
} catch {
print(error.localizedDescription)
}
您还可以嵌套结构来表示您可能必须要做的数据。在 this guide to JSON parsing
上查看 "More Complex Nested Response"我最终将 "Location" 结构更改为
- 不可编码
- 将每个 属性 作为参数而不是将整个 JSON 字典作为参数
在 "performGoogleSearch()" 函数中,我基本上必须不断将字典的值转换为字典本身,以便更深入地研究文件。然后我使用我可以从 JSON 文件中得到的每个值,并使用它们创建我的 class 的对象。然后我将每个对象附加到我的结果数组中。
func performGoogleSearch(radius: Double, type: String, price: Int ) {
let location = locationManager.location?.coordinate
let url: URL = URL(string: "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(location?.latitude ?? 0),\(location?.longitude ?? 0)&radius=\(radius * 1609.34)&type=restaurant&maxprice=\(price)&key=AIzaSyBF0uwjr6BZc-Y-0kPsMBq2zNkl5EArioQ")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
let jsonObject = try? JSONSerialization.jsonObject(with: data! as Data, options: [])
if let jsonArray = jsonObject as? [String: Any] {
if let results = jsonArray["results"] as! [Any]?{
for result in results {
if let locationDictionary = result as? [String : Any] {
let geometry = locationDictionary["geometry"]! as! [String : Any]
let location = geometry["location"]! as! [String : Any]
let lat = location["lat"]
let long = location["lng"]
let openingHours = locationDictionary["opening_hours"] as? [String : Any]
let openNow = openingHours?["open_now"]
let photos = locationDictionary["photos"] as? [[String : Any]]
let newLocation = Location(lat: lat as! Double, long: long as! Double, id: locationDictionary["id"] as? String, name: locationDictionary["name"] as! String, openNow: openNow as? Int, photos: photos, placeID: locationDictionary["place_id"] as? String, priceLevel: locationDictionary["price_level"] as? Int, rating: locationDictionary["rating"] as? Double, types: locationDictionary["types"] as? [String])
googleResults.append(newLocation!)
}
}
print("Results: \(googleResults.count)")
let randomInt = Int(arc4random_uniform(UInt32(googleResults.count)))
print("RandomInt: \(randomInt)")
if googleResults.count != 0 {
self.googleResult = googleResults[randomInt]
self.annotation = MapBoxAnnotation(coordinate: CLLocationCoordinate2D(latitude: (self.self.googleResult?.lat)!, longitude: (self.self.googleResult?.long)!), title: self.googleResult?.name, subtitle: nil)
}
}
}
DispatchQueue.main.async {
self.animateResultView()
}
}
task.resume()
位置结构:
struct Location {
var lat: Double
var long: Double
var id: String?
var name: String
var openNow: Int?
var photos: [[String : Any]]?
var placeID: String?
var priceLevel: Int?
var rating: Double?
var types: [String]?
init?(lat: Double, long: Double, id: String?, name: String, openNow: Int?, photos: [[String : Any]]?, placeID: String?, priceLevel: Int?, rating: Double?, types: [String]?) {
self.lat = lat
self.long = long
self.id = id
self.name = name
self.openNow = openNow
self.photos = photos
self.placeID = placeID
self.priceLevel = priceLevel
self.rating = rating
self.types = types
}
}