C# - 格式化Yelp API输出

时间:2016-06-17 11:49:56

标签: c# json api formatting yelp

所以我一般都是API的新手。他们很兴奋,因为我实际上可以开始制作真正的节目。也就是说,我已经弄清楚如何从Yelp中获取结果。问题是,它们的格式如下:

{
    "businesses": [
        {
            "categories": [
                [
                    "Local Flavor",
                    "localflavor"
                ],
                [
                    "Mass Media",
                    "massmedia"
                ]
            ],
            "display_phone": "+1-415-908-3801",
            "id": "yelp-san-francisco",
            "image_url": "http://s3-media3.fl.yelpcdn.com/bphoto/nQK-6_vZMt5n88zsAS94ew/ms.jpg",
            "is_claimed": true,
            "is_closed": false,
            "location": {
                "address": [
                    "140 New Montgomery St"
                ],
                "city": "San Francisco",
                "coordinate": {
                    "latitude": 37.7867703362929,
                    "longitude": -122.399958372115
                },
                "country_code": "US",
                "cross_streets": "Natoma St & Minna St",
                "display_address": [
                    "140 New Montgomery St",
                    "Financial District",
                    "San Francisco, CA 94105"
                ],
                "geo_accuracy": 9.5,
                "neighborhoods": [
                    "Financial District",
                    "SoMa"
                ],
                "postal_code": "94105",
                "state_code": "CA"
            },
            "mobile_url": "http://m.yelp.com/biz/yelp-san-francisco",
            "name": "Yelp",
            "phone": "4159083801",
            "rating": 2.5,
            "rating_img_url": "http://s3-media4.fl.yelpcdn.com/assets/2/www/img/c7fb9aff59f9/ico/stars/v1/stars_2_half.png",
            "rating_img_url_large": "http://s3-media2.fl.yelpcdn.com/assets/2/www/img/d63e3add9901/ico/stars/v1/stars_large_2_half.png",
            "rating_img_url_small": "http://s3-media4.fl.yelpcdn.com/assets/2/www/img/8e8633e5f8f0/ico/stars/v1/stars_small_2_half.png",
            "review_count": 7140,
            "snippet_image_url": "http://s3-media4.fl.yelpcdn.com/photo/YcjPScwVxF05kj6zt10Fxw/ms.jpg",
            "snippet_text": "What would I do without Yelp?\n\nI wouldn't be HALF the foodie I've become it weren't for this business.    \n\nYelp makes it virtually effortless to discover new...",
            "url": "http://www.yelp.com/biz/yelp-san-francisco"
        }
    ],
    "total": 2316
}

我不明白如何将这些数据分开并在其中插入正确的格式以便在WinForm或网页上正常显示。我似乎没有办法访问每个数据。我输入了“回复”。在IDE中引用了JObject,但是例如,没有名为response.is_closed的bool类型......下面是我的简单程序的代码。显然我想将它转换为Web应用程序或WinForm,但我甚至会在命令行窗口中探索它的格式,因为这样显示的数据很难看。谢谢。

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using CommandLine;
using Newtonsoft.Json.Linq;
using SimpleOAuth;

/// <summary>
/// Yelp API v2.0 code sample.
/// This program demonstrates the capability of the Yelp API version 2.0
/// by using the Search API to query for businesses by a search term and location,
/// and the Business API to query additional information about the top result
/// from the search query.
///
/// Please refer to http://www.yelp.com/developers/documentation for the API documentation.
///
/// Sample usage of the program:
/// `YelpAPI.exe --term="bars" --location="San Francisco, CA"`
/// </summary>
namespace YelpAPI
{
    /// <summary>
    /// Class that encapsulates the logic for querying the API.
    ///
    /// Users have to set the OAuth credentials properties
    /// in order to use this class.
    /// </summary>
    class YelpAPIClient
    {
        /// <summary>
        /// Consumer key used for OAuth authentication.
        /// This must be set by the user.
        /// </summary>
        private const string CONSUMER_KEY = "CENSORED";

        /// <summary>
        /// Consumer secret used for OAuth authentication.
        /// This must be set by the user.
        /// </summary>
        private const string CONSUMER_SECRET = "CENSORED";

        /// <summary>
        /// Token used for OAuth authentication.
        /// This must be set by the user.
        /// </summary>
        private const string TOKEN = "CENSORED";

        /// <summary>
        /// Token secret used for OAuth authentication.
        /// This must be set by the user.
        /// </summary>
        private const string TOKEN_SECRET = "CENSORED";

        /// <summary>
        /// Host of the API.
        /// </summary>
        private const string API_HOST = "https://api.yelp.com";

        /// <summary>
        /// Relative path for the Search API.
        /// </summary>
        private const string SEARCH_PATH = "/v2/search/";

        /// <summary>
        /// Relative path for the Business API.
        /// </summary>
        private const string BUSINESS_PATH = "/v2/business/";

        /// <summary>
        /// Search limit that dictates the number of businesses returned.
        /// </summary>
        private const int SEARCH_LIMIT = 3;

        /// <summary>
        /// Prepares OAuth authentication and sends the request to the API.
        /// </summary>
        /// <param name="baseURL">The base URL of the API.</param>
        /// <param name="queryParams">The set of query parameters.</param>
        /// <returns>The JSON response from the API.</returns>
        /// <exception>Throws WebException if there is an error from the HTTP request.</exception>
        private JObject PerformRequest(string baseURL, Dictionary<string, string> queryParams=null)
        {
            var query = System.Web.HttpUtility.ParseQueryString(String.Empty);

            if (queryParams == null)
            {
                queryParams = new Dictionary<string, string>();
            }

            foreach (var queryParam in queryParams)
            {
                query[queryParam.Key] = queryParam.Value;
            }

            var uriBuilder = new UriBuilder(baseURL);
            uriBuilder.Query = query.ToString();

            var request = WebRequest.Create(uriBuilder.ToString());
            request.Method = "GET";

            request.SignRequest(
                new Tokens {
                    ConsumerKey = CONSUMER_KEY,
                    ConsumerSecret = CONSUMER_SECRET,
                    AccessToken = TOKEN,
                    AccessTokenSecret = TOKEN_SECRET
                }
            ).WithEncryption(EncryptionMethod.HMACSHA1).InHeader();

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            var stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
            return JObject.Parse(stream.ReadToEnd());
        }

        /// <summary>
        /// Query the Search API by a search term and location.
        /// </summary>
        /// <param name="term">The search term passed to the API.</param>
        /// <param name="location">The search location passed to the API.</param>
        /// <returns>The JSON response from the API.</returns>
        public JObject Search(string term, string location)
        {
            string baseURL = API_HOST + SEARCH_PATH;
            var queryParams = new Dictionary<string, string>()
            {
                { "term", term },
                { "location", location },
                { "limit", SEARCH_LIMIT.ToString() }
            };
            return PerformRequest(baseURL, queryParams);
        }

        /// <summary>
        /// Query the Business API by a business ID.
        /// </summary>
        /// <param name="business_id">The ID of the business to query.</param>
        /// <returns>The JSON response from the API.</returns>
        public JObject GetBusiness(string business_id)
        {
            string baseURL = API_HOST + BUSINESS_PATH + business_id;
            return PerformRequest(baseURL);
        }
    }

    /// <summary>
    /// Command-line options abstraction.
    /// </summary>
    class Options
    {
        /// <summary>
        /// Gets and sets the Term property.
        /// </summary>
        /// <value>The search term specified by the user.</value>
        [Option('t', "term", DefaultValue="dinner", HelpText = "Search term")]
        public string Term { get; set; }

        /// <summary>
        /// Gets and sets the Location property.
        /// </summary>
        /// <value>The location term specified by the user.</value>
        [Option('l', "location", DefaultValue="San Francisco, CA", HelpText = "Search Location")]
        public string Location { get; set; }
    }

    /// <summary>
    /// Class that encapsulates the program entry point.
    /// </summary>
    class Program
    {
        /// <summary>
        /// Queries the API by the input values from the user, and prints
        /// the result on the console.
        /// </summary>
        /// <param name="term">The search term to query.</param>
        /// <param name="location">The location of the business to query.</param>
        public static void QueryAPIAndPrintResult(string term, string location)
        {
            var client = new YelpAPIClient();

            Console.WriteLine("Querying for {0} in {1}...", term, location);

            JObject response = client.Search(term, location);

            JArray businesses = (JArray)response.GetValue("businesses");

            if (businesses.Count == 0)
            {
                Console.WriteLine("No businesses for {0} in {1} found.", term, location);
                return;
            }

            string business_id = (string)businesses[0]["id"];

            Console.WriteLine(
                "{0} businesses found, querying business info for the top result \"{1}\"...",
                businesses.Count,
                business_id
            );

            response = client.GetBusiness(business_id);

            Console.WriteLine(String.Format("Result for business {0} found:", business_id));        
            Console.WriteLine(response.ToString());
        }

        /// <summary>
        /// Program entry point.
        /// </summary>
        /// <param name="args">The command-line arguments.</param>
        static void Main(string[] args)
        {
            bool exit = false;
            do
            {
                var options = new Options();
                string locationInput = "";
                string businessTypeInput = "";
                try
                {
                    CommandLine.Parser.Default.ParseArguments(args, options);
                }
                catch (CommandLine.ParserException)
                {
                    Console.Error.WriteLine("Failed to parse command line options.");
                    Console.ReadKey();
                    Environment.Exit(-1);
                }

                try
                {
                    Console.WriteLine("Enter the location: ");
                    locationInput = Console.ReadLine();
                    Console.WriteLine("Enter the type of business:");
                    businessTypeInput = Console.ReadLine();
                    Program.QueryAPIAndPrintResult(businessTypeInput, locationInput);
                    Console.WriteLine("Would you like to search again? Y/N?");
                    if (Console.ReadLine().ToUpper() == "N")
                        exit = true;
                    else
                        exit = false;
                }
                catch (WebException error)
                {
                    if (error.Response != null)
                        using (var reader = new StreamReader(error.Response.GetResponseStream()))
                        {
                            Console.Error.WriteLine("Response returned: {0}", reader.ReadToEnd());
                        }

                    Console.Error.WriteLine("HTTP request failed, got {0}, abort program.", error.Message);
                }
            } while (exit == false);
                Console.ReadKey();
                Environment.Exit(-1);
            }
        }
    }

文档在这里:https://www.yelp.com/developers/documentation/v2/search_api

其中列出了我应该能够抓取的所有数据。

如果你想运行这个,你需要你可以在这里获得的Oauth信息:https://www.yelp.com/developers/manage_api_keys

1 个答案:

答案 0 :(得分:1)

我在寻找Yelp API的一些信息时发现了你的问题,所以我自己就这样做了。如果您还没有找到答案,可以通过几种方法解析json对象。在以下两个示例中,您只需要提取业务,然后循环遍布业务中的列表。

//yelpJsonReturned is whatever you named your Json object returned by the API.
//"businesses" indicates that you only want the parts of that object listed under businesses
var businesses = yelpJsonReturned["businesses"]

foreach (JsonValue business in businesses)
{
     //parsing code goes here
}

1)

//parsing code goes here
var businessList = JsonConvert.DeserializeObject<List<YelpListing>>(yourJsonString)

这将获取每个列表并将其映射到您已创建的YelpListing模型。不幸的是,我没有运气,因为YelpListing模型必须与GET请求返回的内容完全匹配,并且我不断收到类型转换错误,因为API的返回字符串有点复杂。此外,它有很多我不需要使用的信息。

2)您还可以使用与yelpJsonReturned["businesses"]相同的想法来提取业务字符串的各个部分。鉴于在这个Json对象中嵌套,我发现最简单的方法是单独拉出对象,然后将它们全部映射到我可以在程序中的其他地方使用的平面模型中。它可能不是最有效的方法,但我喜欢我对后续模型的控制,它确实让我在映射到YelpListing对象时有些沮丧。这是我用的。

var yelpListingList = new List<YelpListing>();

var businesses = yelpJsonReturned["businesses"];

foreach (JsonValue business in businesses)
{
    //parsing code goes here

    var location = business["location"];
    var address = location["address"];
    var coordinates = location["coordinate"];

    var listing = new YelpListing()
    {
        Id = business["id"],
        Name = business["name"],
        Address = address[0],
        City = location["city"],
        Latitude = coordinates["latitude"],
        Longitude = coordinates["longitude"],
        LocationClosed = business["is_closed"],
        MobileUrl = business["mobile_url"],
        Rating = business["rating"],
        NumberReviews = business["review_count"],
        RatingImage = business["rating_img_url_small"]
    };

    yelpListingList.Add(listing);
}