技术开发 频道

Windows phone如何实现json接口的调用

  【IT168技术】作为微博界的鼻祖,Twitter极大地改变了我们的生活!目前国内各大微博网站也如雨后春笋般出现并被我们熟悉和使用,微博也进入手机成为除即时通讯外的第二大热门应用。

  目前QQ、新浪、搜狐微博都开放了API供开发人员调用,本文就是将从如何调用最简单的json类型的接口开始逐步深入微博客户端的开发。

  因为各大客户端的API调用都需要用户传入appkey和用户名、密码等信息,基于循序渐进的考虑,我们将从一个最简单的第三方接口调用展开,以展示在WP7上是如何调用json类型接口的。

  目前Twitter处于被墙的状态,但是一些第三方网站提供了相应的代理或者封装。比如说我们就可以在http://whatthetrend.com/ 这个网站上来查看Twitter当前最热的10个话题。

  注册获取appkey

  该网站提供了一个Web服务,并用json数据格式返回10大热门话题。该Web服务的相关说明可以在http://api.whatthetrend.com/ 看到。我们在项目中调用的唯一接口如下:

  http://api.whatthetrend.com/api/v2/trends.json?api_key={0}

  这里{0}就是该接口需要的appkey,笔者已经为你申请好了,为“1eb228f23d41dd3e8a042af5cf072ccfe41d0c22”。

  如果该appkey失效的话,那么你可以在http://api.whatthetrend.com/页面的右侧填写相关的信息来获得一个appkey。如下图示:


  解析JSON

  我们知道上述接口返回的数据是json格式的,为此我们需要通过C#对json类型的数据进行解析。为此我们在项目中添加System.ServiceModel.Web.dll的引用,以便使用DataContractJsonSerializer类。

解析JSON

  调用http://api.whatthetrend.com/api/v2/trends.json?api_key=1eb228f23d41dd3e8a042af5cf072ccfe41d0c22接口返回的json格式数据如下:

{
      
"api_version" : "2.0",
      
"as_of" : "2009-10-15 19:57:01",
      
"trends" : [
          {
"description" : { "created_at" : "2009-10-15 19:54:32",
                
"text" : "A 6 year old was believed to be stuck in a homemade hot air balloon in Denver, Colorado. The balloon landed with no boy found inside. The boy is still missing.",
                
"score" : "0"
              },
            
"first_trended_at" : "2009-10-15 19:00:01",
            
"last_trended_at" : "2009-10-15 19:55:01",
            
"name" : "Colorado",
            
"newly_trending" : "0",
            
"query" : "Colorado",
            
"trend_index" : "1",
            
"url" : "http://search.twitter.com/search?q=Colorado",
            
"category_id" : "11",
            
"category_name" : "News",
            
"locked" : false
          },
          {
"description" : { "created_at" : "2009-10-15 19:54:10",
                
"text" : "A 6 year old was believed to be stuck in a homemade hot air balloon in Denver, Colorado. The balloon landed with no boy found inside. The boy is still missing.",
                
"score" : "0"
              },
            
"first_trended_at" : "2009-10-15 19:30:01",
            
"last_trended_at" : "2009-10-15 19:55:01",
            
"name" : "#saveballoonboy",
            
"newly_trending" : "0",
            
"query" : "#saveballoonboy",
            
"trend_index" : "2",
            
"url" : "http://search.twitter.com/search?q=%23saveballoonboy",
            
"category_id" : "11",
            
"category_name" : "News",
            
"locked" : false
          }, ...
        ]
    }
    

  是的,这样的数据看起来是不是非常吓人,这里已经将一些关键的数据字段用红色字体标记出来。我们可以将这个json数据分为三部分

  api_version

  trends

  as_of

  而trends 是由如下属性构成的:

  name

  trend_id

  url

  category_id

  category_name

  query

  description

  first_trended_at

  last_trended_at

  newly_trending

  trend_index

  locked

  description是由如下属性构成的:

  created_at

  text

  score

  接下来我们需要使用C#构建这些数据的模式类,以便在程序中装配和使用数据。下面是这些类的代码。

/// <summary>
/// Model for twitter trend description
/// </summary>
public class TrendDescription
{
    
/// <summary>
    
/// Gets or sets the created_at.
    
/// </summary>
    
/// <value>The created_at.</value>
    
public DateTime created_at { get; set; }

    
/// <summary>
    
/// Gets or sets the text.
    
/// </summary>
    
/// <value>The text.</value>
    
public string text { get; set; }

    
/// <summary>
    
/// Gets or sets the score.
    
/// </summary>
    
/// <value>The score.</value>
    
public int score { get; set; }
}

/// <summary>
/// Model for twitter trend
/// </summary>
public class Trend
{
    
/// <summary>
    
/// Gets or sets the description.
    
/// </summary>
    
/// <value>The description.</value>
    
public TrendDescription description { get; set; }

    
/// <summary>
    
/// Gets or sets the first_trended_at.
    
/// </summary>
    
/// <value>The first_trended_at.</value>
    
public DateTime first_trended_at { get; set; }

    
/// <summary>
    
/// Gets or sets the last_trended_at.
    
/// </summary>
    
/// <value>The last_trended_at.</value>
    
public DateTime last_trended_at { get; set; }

    
/// <summary>
    
/// Gets or sets the name.
    
/// </summary>
    
/// <value>The name.</value>
    
public string name { get; set; }

    
/// <summary>
    
/// Gets or sets the newly_trending.
    
/// </summary>
    
/// <value>The newly_trending.</value>
    
public int newly_trending { get; set; }

    
/// <summary>
    
/// Gets or sets the query.
    
/// </summary>
    
/// <value>The query.</value>
    
public string query { get; set; }

    
/// <summary>
    
/// Gets or sets the trend_index.
    
/// </summary>
    
/// <value>The trend_index.</value>
    
public int trend_index { get; set; }

    
/// <summary>
    
/// Gets or sets the URL.
    
/// </summary>
    
/// <value>The URL.</value>
    
public string url { get; set; }

    
/// <summary>
    
/// Gets or sets the category_id.
    
/// </summary>
    
/// <value>The category_id.</value>
    
public int category_id { get; set; }

    
/// <summary>
    
/// Gets or sets the category_name.
    
/// </summary>
    
/// <value>The category_name.</value>
    
public string category_name { get; set; }

    
/// <summary>
    
/// Gets or sets a value indicating whether this <see cref="Trend"/> is locked.
    
/// </summary>
    
/// <value><c>true</c> if locked; otherwise, <c>false</c>.</value>
    
public bool locked { get; set; }
}

/// <summary>
/// Model for trends results
/// </summary>
public class TrendsResults
{
    
/// <summary>
    
/// Gets or sets the api_version.
    
/// </summary>
    
/// <value>The api_version.</value>
    
public string api_version { get; set; }

    
/// <summary>
    
/// Gets or sets the as_of.
    
/// </summary>
    
/// <value>The as_of.</value>
    
public DateTime as_of { get; set; }

    
/// <summary>
    
/// Gets or sets the trends.
    
/// </summary>
    
/// <value>The trends.</value>
    
public Trend[] trends { get; set; }
}

  现在我们就可以使用 DataContractJsonSerializer 来将json类型的数据装配到C#对象上。下面是实现解析的代码:

DataContractJsonSerializer dataContractJsonSerializer =
    
new DataContractJsonSerializer(typeof(TrendsResults));
TrendsResults trendsResults
=
    (TrendsResults)dataContractJsonSerializer.ReadObject(stream);

  上面代码中的stream是一个包含json数据的Stream对象。

  实现热门话题数据获取服务

  知道了怎么解析数据后,我们现在将上面所有的实现封装在方法中。

  在GetTrends方法中,使用了一些委托作为参数,以便我们的类可以异步工作。

  l Action> onGetTrendsCompleted, 在热门主题数据准备处理时调用。

  l Action onError, 在获取热门主题信息发生错误时调用。

  l Action onFinally, 总是被调用, 无论是否有错误发生.

  因此方法的签名如下:

public static void GetTrends(Action<IEnumerable<Trend>>
    onGetTrendsCompleted
= null, Action<Exception> onError = null,
    Action onFinally
= null)

  接下来我们需要WebClient来请求服务器端,以获取json数据。

WebClient webClient = new WebClient();

// register on download complete event
webClient.OpenReadCompleted
+= delegate(object sender, OpenReadCompletedEventArgs e)
{
    ...
};

webClient.OpenReadAsync(
new Uri(string.Format
    (WhatTheTrendSearchQuery, WhatTheTrendApplicationKey)));

  这里的WhatTheTrendSearchQuery的定义如下:

  private const string WhatTheTrendSearchQuery =

  "http://api.whatthetrend.com/api/v2/trends.json?api_key={0}";

  onGetTrendsCompleted, onError, onFinally的事件处理代码如下:

/// <summary>
/// Gets the trends.
/// </summary>
/// <param name="onGetTrendsCompleted">The on get trends completed.</param>
/// <param name="onError">The on error.</param>
public static void GetTrends(Action<IEnumerable<Trend>>
    onGetTrendsCompleted
= null, Action<Exception> onError = null,
    Action onFinally
= null)
{
    WebClient webClient
= new WebClient();

    
// register on download complete event
    webClient.OpenReadCompleted
+=
    delegate(
object sender, OpenReadCompletedEventArgs e)
    {
        try
        {
            
// report error
            
if (e.Error != null)
            {
                
if (onError != null)
                {
                    onError(e.Error);
                }
                return;
            }

            
// convert json result to model
            Stream stream
= e.Result;
            DataContractJsonSerializer dataContractJsonSerializer
=
        
new DataContractJsonSerializer(typeof(TrendsResults));
            TrendsResults trendsResults
=
        (TrendsResults)dataContractJsonSerializer.ReadObject(stream);

            
// notify completed callback
            
if (onGetTrendsCompleted != null)
            {
                onGetTrendsCompleted(trendsResults.trends);
            }
        }
        finally
        {
            
// notify finally callback
            
if (onFinally != null)
            {
                onFinally();
            }
        }
    };

    webClient.OpenReadAsync(
new Uri(string.Format
    (WhatTheTrendSearchQuery, WhatTheTrendApplicationKey)));
}

  使用热门话题服务

  最后为了在页面上显示10大热门信息,我们可以在MainPage.xmal.cs中放入如下的代码,以便实现数据和列表控件的绑定。

private void Button_Click(object sender, RoutedEventArgs e)
        {
            TwitterService.GetTrends(
               (items)
=> { listbox.ItemsSource = items; },
               (exception)
=> { MessageBox.Show(exception.Message); },
              
null
               );
        }
0
相关文章