Yelp API业务详细信息端点

问题描述 投票:0回答:1

能够从业务匹配端点检索到业务ID之后,我现在正尝试使用该业务ID将其传递到业务详细信息端点。我正在学习有关调用API的知识,所以请耐心等待。谢谢!

以下代码使我可以进行业务匹配:

调用API->

import Foundation
import Moya


private let apiKey = ""


enum YelpService {
    enum BusinessMatch: TargetType {
        case match(name: String, address1: String, city: String, state: String, country: String)

        public var baseURL: URL { return NSURL(string: "https://api.yelp.com")! as URL
        }


        public var path: String {
            switch self {
            case .match:
                return "/v3/businesses/matches"
            }
        }

        var method: Moya.Method {
            return.get
        }

        var sampleData: Data {
            return Data()
        }

        var task: Task {
            switch self {
            case let .match(name, address1, city, state, country):
                return .requestParameters(parameters: ["name": name, "address1": address1, "city": city, "state": state, "country": country, "limit": 1], encoding: URLEncoding.queryString)
            }
        }

        var headers: [String : String]? {
            return ["Authorization": "Bearer \(apiKey)"]
        }
}
}

返回业务匹配端点->

import UIKit
import CoreData
import Moya

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    let service = MoyaProvider<YelpService.BusinessMatch>()


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        service.request(.match(name: "Sushi Damo", address1:
            "330 W 58th St", city: "New York", state: "NY", country: "US")) { (result) in
                switch result {
                case .success(let response):
                    print(try? JSONSerialization.jsonObject(with: response.data, options: []))
                case .failure(let error):
                    print("Error: \(error)")
                }
        }
        return true
}




    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }

    // MARK: - Core Data stack

    lazy var persistentContainer: NSPersistentContainer = {
        /*
         The persistent container for the application. This implementation
         creates and returns a container, having loaded the store for the
         application to it. This property is optional since there are legitimate
         error conditions that could cause the creation of the store to fail.
        */
        let container = NSPersistentContainer(name: "APITest")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                /*
                 Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
}

在致电业务匹配端点后,我收到以下信息:

Optional({
    businesses =     (
                {
            alias = "sushi-damo-new-york";
            coordinates =             {
                latitude = "40.76778";
                longitude = "-73.98358";
            };
            "display_phone" = "(212) 707-8609";
            id = J85NKgA4tOgBAoqxu0vBNw;
            location =             {
                address1 = "330 W 58th St";
                address2 = "";
                address3 = "";
                city = "New York";
                country = US;
                "display_address" =                 (
                    "330 W 58th St",
                    "New York, NY 10019"
                );
                state = NY;
                "zip_code" = 10019;
            };
            name = "Sushi Damo";
            phone = "+12127078609";
        }
    );
})

我希望能够从任何业务匹配结果中自动提取该业务ID。问题出在以下代码中。

调用API->

enum YelpDetails {
    enum BusinessDetail: TargetType {
        case BusinessID(id: String)

        public var baseURL: URL { return NSURL(string: "https://api.yelp.com")! as URL
        }

        public var path: String {
            switch self {
            case .BusinessID:
                return "https://api.yelp.com/v3/businesses/{id}"
            }
        }

        var method: Moya.Method {
            return.get
        }

        var sampleData: Data {
            return Data()
        }

        var task: Task {
            switch self {
            case let .BusinessID(id):
                return .requestParameters(parameters: ["BusinessID": id], encoding: URLEncoding.queryString)
            }
        }

        var headers: [String : String]? {
            return ["Authorization": "Bearer \(apiKey)"]
        }
    }
}

从业务详细信息端点返回结果->

   let information = MoyaProvider<YelpDetails.BusinessDetail>()

    func call(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        information.request(.BusinessID(id: "J85NKgA4tOgBAoqxu0vBNw")) {
            (result) in
            switch result {
            case .success(let response):
                print(try? JSONSerialization.jsonObject(with:
                    response.data, options: []))
            case .failure(let error):
                print("Error: \(error)")
            }
        }
        return true
}
ios swift api yelp yelp-fusion-api
1个回答
1
投票

[通常,当您从网络上获取JSON数据时,您想要做的就是将其序列化为可以在Swift中使用的对象。幸运的是,Swift提供了可轻松将json转换为对象并再次转换回的工具,即Codable协议。请查看this video了解更多信息。但是从本质上讲,这是要查看我们从服务器获得的响应,并创建一个反映该响应的structclass。因此,从您的服务器返回的原始json如下所示:

{
    "businesses": [
        {
            "id": "J85NKgA4tOgBAoqxu0vBNw",
            "alias": "sushi-damo-new-york",
            "name": "Sushi Damo",
            "coordinates": {
                "latitude": 40.76778,
                "longitude": -73.98358
            },
            "location": {
                "address1": "330 W 58th St",
                "address2": "",
                "address3": "",
                "city": "New York",
                "zip_code": "10019",
                "country": "US",
                "state": "NY",
                "display_address": [
                    "330 W 58th St",
                    "New York, NY 10019"
                ]
            },
            "phone": "+12127078609",
            "display_phone": "(212) 707-8609"
        }
    ]
}

这是具有一个键businesses的字典,其字典数组的值带有描述业务的键值对。使用上面的JSON,数组中只有一个元素。

所以现在我们对响应的外观有所了解,我们可以开始创建一些符合Codable的结构。我们知道我们需要一个具有属性struct的顶级businesses,该属性是一个包含描述每个业务的结构的数组。

struct BusinessesResponse: Codable {
    let businesses: [BusinessResponse]
}

接下来创建BusinessResponse。现在,如果您只关心id,则只需将BusinessResponse设为:

struct BusinessResponse: Codable {
    let id: String
}

然后更新您在此处的回复方式:

    service.request(.match(name: "Sushi Damo", address1:
            "330 W 58th St", city: "New York", state: "NY", country: "US")) { (result) in
                switch result {
                case .success(let response):
                    print(try? JSONSerialization.jsonObject(with: response.data, options: []))
                case .failure(let error):
                    print("Error: \(error)")
                }
        }

而不是序列化JSON对象,我们要解码为BusinessesResponse结构,我们可以通过将switch语句更新为:

switch result {
case .success(let response):
    let businessesResponse = try? JSONDecoder().decode(BusinessesResponse.self, from: response.data)
    let firstID = businessesResponse?.businesses.first?.id
    // Do something with ID
case .failure(let error):
    print("Error: \(error)")
}

我认为下一个要求不会像书面要求那样有效。在此请求中,通过URL的路径发送参数,即企业的ID。因此,path应为:

       public var path: String {
            switch self {
            case let .BusinessID(id):
                return "v3/businesses/\(id)"
            }
        }

因此task不再需要处理参数,应该是:

        var task: Task {
            switch self {
            case .BusinessID:
                return .requestParameters(parameters:[:], encoding: URLEncoding.queryString)
            }
        }
© www.soinside.com 2019 - 2024. All rights reserved.