现代操作系统应用开发之UWP开发 ------ API的获取以及C#中Json的解析(天气预报的获取和历史上的今天查询)

做这个小程序的时候,看了好多网上的Json解析的方法,主要流行的是使用Newtonsoft.Json类库来实现, 我也下载了并照着做,但是出一些奇怪的报错并不知道怎么解决,然后看了一个Bob Tabor大叔的一节视频,发现讲的简单易懂,实现起来也非常简单,现在就展示一下这种方法(博客最底部有完整源代码)

这里是整个项目文件压缩包的传送门,点击这里

结果展示

这里写图片描述

这里写图片描述

1、API选择

  • 这里我用的是阿凡达数据,选择的是实现天气预报的接口。
  • 进去该网站之后,按照江湖规矩先注册登录,找到想要找的API点击右边的申请数据(一般API都有查询次数的限制,有的还需要付费)
    这里写图片描述
  • 然后再返回这个页面就可以看到能够使用了
    这里写图片描述
  • 点击申请示例看下得到的数据是什么样纸
    这里写图片描述

2、获取实体类

  • 上面能够成功返回Json类型的文本,但是还是不很清楚数据之间的联系,我们用到一个转换Json为C#的网站点这里(别的博客也有推荐一些转换的网站,但是会有问题,比如我这里的Json里面有两个PM25,某些网站就会将这两个类都叫PM25,造成类名重复,后面就很麻烦,而这个网站能够自己加后缀区分相同名称的类)将那些看不懂的数据转换为比较有结构的C#实体类,把上面示例得到的Json文本复制进去点击Generate就好了,就是下面这个样子了
    这里写图片描述
    证明一下类名相同的情况
    这里写图片描述
    然后呢,直接把得到的C#实体类复制,待会要用

3、实现解析Json返回实体类的方法(?或者叫做函数)

  • 到现在还没创建项目,在VS中创建好一个新项目,新建一个类叫做OpenHistoryToday,然后在这个类的外面粘贴刚刚得到的实体类
    这里写图片描述
  • 可以看到OpenHistoryToday中我还写了一个方法叫做GetWeather,这个就是核心的代码了,现在看看这个怎么写的
public async static Task<RootObject> GetWeather(String city)
        {
            Uri uri = new Uri(uriString: "http://api.avatardata.cn/Weather/Query?key=0151ec4ce80149ef8ba24b197c36a44f&cityname=" + city);//Uri页面为Json字符串或XML字符串

            HttpClient client = new HttpClient();
            var response = await client.GetAsync(uri);
            var result = await response.Content.ReadAsStringAsync();
            var serializer = new DataContractJsonSerializer(typeof(RootObject));

            var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
            var data = (RootObject)serializer.ReadObject(ms);

            return data;
        }
  • 因为是异步的方法,所以要用Task修饰,表示在执行查询及解析的过程中返回的数据可能不是RootObject类型,而是一种临时的数据类型,等到数据完全解析成功之后返回RootObject,具体如图(这里的额RootObject是得到数据的最顶层类,认真看看刚刚得到的实体类,需要理清一下关系,应该不难)
  • 这里做的工作就是先用数据API的网址创建一个Uri,再创建一个HttpClient并通过异步的方法获取该Uri返回的数据,通过程序集 System.Runtime.Serialization.Json里面的DataContractJsonSerializer类的ReadObject方法返回RootObject类型的变量(还是System自带的程序包好用啊!)
  • 对了,直接这样的话有问题,可以发现上面中我的实体类前面加了点东西,因为需要在每个类前面加上Attribute的数据契约关键字([DataContract]),以及在类的成员前面加上[DataMember],这样的话写的方法才能正确识别RootObject类,这是关于C#的特性(Attribute)知识了
    这里写图片描述

4、UI的布置以及输出格式的处理

  • 接下来我们再来处理一下button的点击事件,倒不是很难,只要正确理解数据类之间的关系就行了
    这里写图片描述
  • 对了还有一点,如果要处理多个API的话,并且他们在同一命名空间下的话就会有类名称的冲突,因为转换得到的都是RootObject,所以要么放在不同命名空间下,要么就更改一下名字
    这里写图片描述

5、完整代码

MainPage.xml

<Page
    x:Class="Week7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Week7"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background= "Beige">
        <ScrollViewer HorizontalAlignment="Center" Margin="0,0,0,0" Name="scrollViewer1" VerticalAlignment="Center" >
            <ScrollViewer.Content>
                <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <TextBox Name="input" HorizontalAlignment="Center" Margin="0,100,0,0" Width="500"  PlaceholderText ="请输入城市名称来查询天气" ></TextBox>
                <Button Name="get" HorizontalAlignment="Center" Margin="50,100,0,0" Content="查询天气" Click="Get_ClickAsync" ></Button>
            </StackPanel>
                    <StackPanel Orientation="Horizontal"  HorizontalAlignment="Center">
                        <DatePicker Name="date" YearVisible="False"   HorizontalAlignment="Center" Margin="0,50,0,0"></DatePicker>
                        <Button Name="search" HorizontalAlignment="Center" Margin="50,50,0,0" Content="查询历史上的今天" Click ="search_Click" ></Button>
                    </StackPanel>
                    <TextBlock Name="ouput" Margin="0,50,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" TextWrapping="Wrap"/>

        </StackPanel>

        </ScrollViewer.Content>

        </ScrollViewer>
    </Grid>
</Page>

MainPage.xml.cs

using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

// https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x804 上介绍了“空白页”项模板

namespace Week7
{
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Get_ClickAsync(object sender, RoutedEventArgs e)
        {
            RootObject myData = await OpenWeatherProxy.GetWeather(input.Text);
            if (myData.error_code != 0)
                ouput.Text = "城市输入错误,请重新输入!";
            else
            {
                Weather  myWeather= myData.result.realtime.weather;
                Wind myWind = myData.result.realtime.wind;
                String myTime = myData.result.realtime.time;
                Pm252 myPm25 = myData.result.pm25.pm25;
                List<Weather2> myFutureWeather = myData.result.weather;

                ouput.Text = "\n城市:" + myData.result.realtime.city_name +
                             "\n更新时间:" + myData.result.realtime.date + " " + myTime +
                            "\n\n天气状况:" + myWeather.info +
                            "\n温度:" + myWeather.temperature + "℃" +
                             "\n湿度:" + myWeather.humidity + " %" +
                             "\n风向:" + myWind.direct +
                             "\n强度:" + myWind.power + "级" +
                             "\nPM 2.5:" + myPm25.quality + "( " + myPm25.des + ") " +
                             "\n\n未来几天天气:" +
                             "\n  *   " + myFutureWeather[1].date + "  " + myFutureWeather[1].info.day[1] +
                             "\n  *   " + myFutureWeather[2].date + "  " + myFutureWeather[2].info.day[1] +
                             "\n  *   " + myFutureWeather[3].date + "  " + myFutureWeather[3].info.day[1] + "\n";

            }


        }

        private async void search_Click(object sender, RoutedEventArgs e)
        {
            HRootObject myData = await OpenHistoryToday.GetHistory(date.Date.Month, date.Date.Day);
            if (myData.error_code != 0)
                ouput.Text = "日期选择错误,请重新选择!";
            else
            {
                ouput.Text = "日期 :" + date.Date.Month + " 月 "  + date.Date.Day +  " 日 " +
                             "\n  *   " + myData.result[0].year + "年   " + myData.result[0].title +
                             "\n  *   " + myData.result[1].year + "年   " + myData.result[1].title +
                             "\n  *   " + myData.result[2].year + "年   " + myData.result[2].title +
                             "\n  *   " + myData.result[3].year + "年   " + myData.result[3].title +
                             "\n  *   " + myData.result[4].year + "年   " + myData.result[4].title +
                             "\n  *   " + myData.result[5].year + "年   " + myData.result[5].title +
                             "\n  *   " + myData.result[6].year + "年   " + myData.result[6].title +
                             "\n  *   " + myData.result[7].year + "年   " + myData.result[7].title +
                             "\n  *   " + myData.result[8].year + "年   " + myData.result[8].title +
                             "\n  *   " + myData.result[9].year + "年   " + myData.result[9].title +
                             "\n  *   " + myData.result[10].year + "年   " + myData.result[10].title;

            }
        }
    }
}

OpenHistoryToday.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;

namespace Week7
{
    class OpenHistoryToday
    {
        public async static Task<HRootObject> GetHistory(int month, int day)
        {
            Uri uri = new Uri(uriString: "http://api.avatardata.cn/HistoryToday/LookUp?key=5d5d2029b3374020b79af443537b88ee&yue=" + month +" &ri=" + day + "&type=1&page=1&rows=15");

            HttpClient client = new HttpClient();
            var response = await client.GetAsync(uri);
            var result = await response.Content.ReadAsStringAsync();
            var serializer = new DataContractJsonSerializer(typeof(HRootObject));

            var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
            var data = (HRootObject)serializer.ReadObject(ms);

            return data;
        }

    }

    [DataContract]
    public class HResult
    {
        [DataMember]
        public int year { get; set; }
        [DataMember]
        public int month { get; set; }
        [DataMember]
        public int day { get; set; }
        [DataMember]
        public string title { get; set; }
        [DataMember]
        public int type { get; set; }
    }
    [DataContract]
    public class HRootObject
    {
        [DataMember]
        public int total { get; set; }
        [DataMember]
        public List<HResult> result { get; set; }
        [DataMember]
        public int error_code { get; set; }
        [DataMember]
        public string reason { get; set; }
    }
}

OpenWeatherProxy.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;

namespace Week7
{
    class OpenWeatherProxy
    {
        public async static Task<RootObject> GetWeather(String city)
        {
            Uri uri = new Uri(uriString: "http://api.avatardata.cn/Weather/Query?key=0151ec4ce80149ef8ba24b197c36a44f&cityname=" + city);//Uri页面为Json字符串或XML字符串

            HttpClient client = new HttpClient();
            var response = await client.GetAsync(uri);
            var result = await response.Content.ReadAsStringAsync();
            var serializer = new DataContractJsonSerializer(typeof(RootObject));

            var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
            var data = (RootObject)serializer.ReadObject(ms);

            return data;
        }
    }
        [DataContract]
        public class Wind
        {
            [DataMember]
            public string windspeed { get; set; }
            [DataMember]
            public string direct { get; set; }
            [DataMember]
            public string power { get; set; }
            [DataMember]
            public string offset { get; set; }
        }
        [DataContract]
        public class Weather
        {
            [DataMember]
            public string humidity { get; set; }
            [DataMember]
            public string img { get; set; }
            [DataMember]
            public string info { get; set; }
            [DataMember]
            public string temperature { get; set; }
        }
        [DataContract]
        public class Realtime
        {
            [DataMember]
            public Wind wind { get; set; }
            [DataMember]
            public string time { get; set; }
            [DataMember]
            public Weather weather { get; set; }
            [DataMember]
            public string dataUptime { get; set; }
            [DataMember]
            public string date { get; set; }
            [DataMember]
            public string city_code { get; set; }
            [DataMember]
            public string city_name { get; set; }
            [DataMember]
            public string week { get; set; }
            [DataMember]
            public string moon { get; set; }
        }
        [DataContract]
        public class Info
        {
            [DataMember]
            public List<string> kongtiao { get; set; }
            [DataMember]
            public List<string> yundong { get; set; }
            [DataMember]
            public List<string> ziwaixian { get; set; }
            [DataMember]
            public List<string> ganmao { get; set; }
            [DataMember]
            public List<string> xiche { get; set; }
            [DataMember]
            public object wuran { get; set; }
            [DataMember]
            public List<string> chuanyi { get; set; }
        }
        [DataContract]
        public class Life
        {
            [DataMember]
            public string date { get; set; }
            [DataMember]
            public Info info { get; set; }
        }
        [DataContract]
        public class Info2
        {
            [DataMember]
            public List<string> dawn { get; set; }
            [DataMember]
            public List<string> day { get; set; }
            [DataMember]
            public List<string> night { get; set; }
        }
        [DataContract]
        public class Weather2
        {
            [DataMember]
            public string date { get; set; }
            [DataMember]
            public string week { get; set; }
            [DataMember]
            public string nongli { get; set; }
            [DataMember]
            public Info2 info { get; set; }
        }
        [DataContract]
        public class Pm252
        {
            [DataMember]
            public string curPm { get; set; }
            [DataMember]
            public string pm25 { get; set; }
            [DataMember]
            public string pm10 { get; set; }
            [DataMember]
            public string level { get; set; }
            [DataMember]
            public string quality { get; set; }
            [DataMember]
            public string des { get; set; }
        }
        [DataContract]
        public class Pm25
        {
            [DataMember]
            public string key { get; set; }
            [DataMember]
            public object show_desc { get; set; }
            [DataMember]
            public Pm252 pm25 { get; set; }
            [DataMember]
            public string dateTime { get; set; }
            [DataMember]
            public string cityName { get; set; }
        }
        [DataContract]
        public class Result
        {
            [DataMember]
            public Realtime realtime { get; set; }
            [DataMember]
            public Life life { get; set; }
            [DataMember]
            public List<Weather2> weather { get; set; }
            [DataMember]
            public Pm25 pm25 { get; set; }
            [DataMember]
            public int isForeign { get; set; }
        }
        [DataContract]
        public class RootObject
        {
            [DataMember]
            public Result result { get; set; }
            [DataMember]
            public int error_code { get; set; }
            [DataMember]
            public string reason { get; set; }
        }
}

没什么文件结构,就是这个样子
这里写图片描述

猜你喜欢

转载自blog.csdn.net/jankingmeaning/article/details/80164596