使用 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" 结构更改为

  1. 不可编码
  2. 将每个 属性 作为参数而不是将整个 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
    }
}