[筆記]透過 HttpClient 取得政府 Open Data 資料轉成物件集合

一直以來,小喵就想找機會玩一下如何從政府公開資料平台取得資料並運用,剛好前幾天小喵去參加一個研討會(打照現代化及持續佈署的ASP.NET網站設計),當中 Demo Fan 大大當場就演練了從政府公開資料平台取得紫外線指數的一個公開資料,小喵就想抽個空來練習看看,沒想到過程中還遇到一些雷,特別記錄下來,以供未來參考

緣起

一直以來,小喵就想找機會玩一下如何從政府公開資料平台取得資料並運用,剛好前幾天小喵去參加一個研討會(打照現代化及持續佈署的ASP.NET網站設計),當中 Demo Fan 大大當場就演練了從政府公開資料平台取得紫外線指數的一個公開資料,小喵就想抽個空來練習看看,沒想到過程中還遇到一些雷,特別記錄下來,以供未來參考

 

政府資料開放平台

這類的資料量越來越多,可以持續的去關注一下,很多好的資源可以利用

而這次要測試的,就是研討會中 Demo Fan 使用的紫外線指數資料:

說明網址:http://data.gov.tw/node/6076

資料網址(JSON):http://opendata.epa.gov.tw/ws/Data/UV/?format=json

 

JSON轉類別設計

首先要接 JSON 資料,我們要在系統中建立一個類別來對應網路上取得的JSON資料,如果要自己分析JSON格式,然後徒手慢慢建立當然可以,可是太累了。其實,對 Visual Studio 2013來說是有個非常方便功能,可以讓系統自己長出類別該有的屬性。

首先,先從網頁上產生JSON

[{"SiteName":"嘉義","UVI":"8","PublishAgency":"中央氣象局","County":"嘉義市","TWD97Lon":"120,25,28","TWD97Lat":"23,29,52","PublishTime":"2014-08-08 14:00"},{"SiteName":"臺中","UVI":"6","PublishAgency":"中央氣象局","County":"臺中市","TWD97Lon":"120,40,33","TWD97Lat":"24,08,51","PublishTime":"2014-08-08 14:00"},{"SiteName":"基隆","UVI":"7","PublishAgency":"中央氣象局","County":"基隆市","TWD97Lon":"121,43,56","TWD97Lat":"25,08,05","PublishTime":"2014-08-08 14:00"},{"SiteName":"恆春","UVI":"6","PublishAgency":"中央氣象局","County":"屏東縣","TWD97Lon":"120,44,17","TWD97Lat":"22,00,20","PublishTime":"2014-08-08 14:00"},{"SiteName":"臺東","UVI":"8","PublishAgency":"中央氣象局","County":"臺東縣","TWD97Lon":"121,08,48","TWD97Lat":"22,45,15","PublishTime":"2014-08-08 14:00"},{"SiteName":"蘭嶼","UVI":"8","PublishAgency":"中央氣象局","County":"臺東縣","TWD97Lon":"121,33,02","TWD97Lat":"22,02,19","PublishTime":"2014-08-08 14:00"},{"SiteName":"鞍部","UVI":"8","PublishAgency":"中央氣象局","County":"臺北市","TWD97Lon":"121,31,12","TWD97Lat":"25,11,11","PublishTime":"2014-08-08 14:00"},{"SiteName":"金門","UVI":"8","PublishAgency":"中央氣象局","County":"金門縣","TWD97Lon":"118,17,21","TWD97Lat":"24,24,27","PublishTime":"2014-08-08 14:00"},{"SiteName":"臺南","UVI":"8","PublishAgency":"中央氣象局","County":"臺南市","TWD97Lon":"120,12,17","TWD97Lat":"22,59,36","PublishTime":"2014-08-08 14:00"},{"SiteName":"澎湖","UVI":"8","PublishAgency":"中央氣象局","County":"澎湖縣","TWD97Lon":"119,33,19","TWD97Lat":"23,34,02","PublishTime":"2014-08-08 14:00"},{"SiteName":"日月潭","UVI":"6","PublishAgency":"中央氣象局","County":"南投縣","TWD97Lon":"120,54,29","TWD97Lat":"23,52,53","PublishTime":"2014-08-08 14:00"},{"SiteName":"臺北","UVI":"7","PublishAgency":"中央氣象局","County":"臺北市","TWD97Lon":"121,30,24","TWD97Lat":"25,02,23","PublishTime":"2014-08-08 14:00"},{"SiteName":"成功","UVI":"7","PublishAgency":"中央氣象局","County":"臺東縣","TWD97Lon":"121,21,55","TWD97Lat":"23,05,57","PublishTime":"2014-08-08 14:00"},{"SiteName":"馬祖","UVI":"7","PublishAgency":"中央氣象局","County":"連江縣","TWD97Lon":"119,55,23","TWD97Lat":"26,10,10","PublishTime":"2014-08-08 14:00"},{"SiteName":"新屋","UVI":"8","PublishAgency":"中央氣象局","County":"桃園縣","TWD97Lon":"121,02,36","TWD97Lat":"25,00,57","PublishTime":"2014-08-08 14:00"},{"SiteName":"花蓮","UVI":"8","PublishAgency":"中央氣象局","County":"花蓮縣","TWD97Lon":"121,36,18","TWD97Lat":"23,58,37","PublishTime":"2014-08-08 14:00"},{"SiteName":"宜蘭","UVI":"7","PublishAgency":"中央氣象局","County":"宜蘭縣","TWD97Lon":"121,44,53","TWD97Lat":"24,45,56","PublishTime":"2014-08-08 14:00"},{"SiteName":"新竹","UVI":"9","PublishAgency":"中央氣象局","County":"新竹縣","TWD97Lon":"121,00,22","TWD97Lat":"24,49,48","PublishTime":"2014-08-08 14:00"},{"SiteName":"玉山","UVI":"8","PublishAgency":"中央氣象局","County":"南投縣","TWD97Lon":"120,57,06","TWD97Lat":"23,29,21","PublishTime":"2014-08-08 14:00"},{"SiteName":"高雄","UVI":"3","PublishAgency":"中央氣象局","County":"高雄市","TWD97Lon":"120,18,29","TWD97Lat":"22,34,04","PublishTime":"2014-08-08 14:00"},{"SiteName":"屏東","UVI":"6","PublishAgency":"環境保護署","County":"屏東縣","TWD97Lon":"120,29,16.92","TWD97Lat":"22,40,23.09","PublishTime":"2014-08-08 14:00"},{"SiteName":"橋頭","UVI":"6","PublishAgency":"環境保護署","County":"高雄市","TWD97Lon":"120,18,20.48","TWD97Lat":"22,45,27.02","PublishTime":"2014-08-08 14:00"},{"SiteName":"新營","UVI":"7","PublishAgency":"環境保護署","County":"臺南市","TWD97Lon":"120,19,2.10","TWD97Lat":"23,18,20.28","PublishTime":"2014-08-08 14:00"},{"SiteName":"朴子","UVI":"9","PublishAgency":"環境保護署","County":"嘉義縣","TWD97Lon":"120,14,50.46","TWD97Lat":"23,27,55.11","PublishTime":"2014-08-08 14:00"},{"SiteName":"塔塔加","UVI":"5","PublishAgency":"環境保護署","County":"嘉義縣","TWD97Lon":"120,52,50.06","TWD97Lat":"23,28,14.19","PublishTime":"2014-08-08 14:00"},{"SiteName":"阿里山","UVI":"2","PublishAgency":"環境保護署","County":"嘉義縣","TWD97Lon":"120,48,05.02","TWD97Lat":"23,30,30.82","PublishTime":"2014-08-08 14:00"},{"SiteName":"斗六","UVI":"9","PublishAgency":"環境保護署","County":"雲林縣","TWD97Lon":"120,32,41.98","TWD97Lat":"23,42,42.67","PublishTime":"2014-08-08 14:00"},{"SiteName":"南投","UVI":"9","PublishAgency":"環境保護署","County":"南投縣","TWD97Lon":"120,41,7.1","TWD97Lat":"23,54,46.8","PublishTime":"2014-08-08 14:00"},{"SiteName":"彰化","UVI":"7","PublishAgency":"環境保護署","County":"彰化縣","TWD97Lon":"120,32,29.47","TWD97Lat":"24,03,57.60","PublishTime":"2014-08-08 14:00"},{"SiteName":"沙鹿","UVI":"8","PublishAgency":"環境保護署","County":"臺中市","TWD97Lon":"120,34,7.66","TWD97Lat":"24,13,32.26","PublishTime":"2014-08-08 14:00"},{"SiteName":"苗栗","UVI":"8","PublishAgency":"環境保護署","County":"苗栗縣","TWD97Lon":"120,49,12.72","TWD97Lat":"24,33,54.97","PublishTime":"2014-08-08 14:00"},{"SiteName":"桃園","UVI":"9","PublishAgency":"環境保護署","County":"桃園縣","TWD97Lon":"121,19,11.87","TWD97Lat":"24,59,41.24","PublishTime":"2014-08-08 14:00"},{"SiteName":"板橋","UVI":"8","PublishAgency":"環境保護署","County":"新北市","TWD97Lon":"121,27,31.2","TWD97Lat":"25,00,46.7","PublishTime":"2014-08-08 14:00"},{"SiteName":"淡水","UVI":"9","PublishAgency":"環境保護署","County":"新北市","TWD97Lon":"121,26,57.26","TWD97Lat":"25,09,52.20","PublishTime":"2014-08-08 14:00"}]

很亂,很不容易看,沒關係,也不需要自己看

接著,在Models裡面,我們新增一個類別,取名叫做 UVInfo 好了,然後只需要在空的類別內容中,找個地方,然後

aaa001

編輯→選擇性貼上→貼上JSON做為類別。不管JSON有多複雜,這樣的一個動作,立馬搞定類別。

Public Class UVInfo
    Public Property SiteName As String
    Public Property UVI As String
    Public Property PublishAgency As String
    Public Property County As String
    Public Property TWD97Lon As String
    Public Property TWD97Lat As String
    Public Property PublishTime As String
End Class

 

撰寫讀取資料的 Dao 類別與 Function

接著開始撰寫存取資料的Dao類別與Function,預定傳回List(Of UVInfo),這樣只需透過ObjectDataSource就可以綁上想展示資料的Server Control

這裡面會用到JSON.NET,HttpClient因此會需要 Import 兩個 NameSpace : System.Net.Http

其中JSON.NET如果專案中沒有,可以透過NuGet取得

而 System.Net.Http這個,如果要Import時發現找不到,可以透過【加入參考】的方式找到加入

 

相關程式碼如下:

Imports System.Net.Http
Imports Newtonsoft.Json

Public Class UVDao
    Public Function GetUVData() As List(Of UVInfo)
        '宣告HttpClient
        Dim client As New HttpClient
        '設定連結的網址
        Dim UVUri As String = "http://opendata.epa.gov.tw/ws/Data/UV/?format=json"
        '取得資料,傳給response(HttpResponseMessage)
        Dim response As HttpResponseMessage = client.GetAsync(UVUri).Result
        '取得JSON的字串
        Dim jsonUVs As String = response.Content.ReadAsStringAsync.Result.ToString
        '透過JsonConvert.DeserializeObject 將 JSON字串 轉成物件集合
        Dim oUVs As List(Of UVInfo) = JsonConvert.DeserializeObject(Of List(Of UVInfo))(jsonUVs)
        '回傳
        Return oUVs
    End Function
End Class

 

 

第一個雷:連線嘗試失敗,因為連線對象有一段時間並未正確回應,或是連線建立失敗,因為連線的主機無法回應。

小喵遇到的第一個雷,就是執行到要透過HttpClient取資料的時候,所遇到的雷,經查後發現 Huan-Lin 老師也遇到過相同的雷,而這雷並非資料來源真的有問題,而是…

由於小喵測試這一段是在公司,但公司有使用Proxy Server來加快並記錄公司內部使用者的網路瀏覽,這問題就是Proxy造成的。小喵立馬切換用手機的網路進行測試,問題也立馬消失不見。

 

第二個雷:

其實第二個雷是,對於JSON.NET的陌生,在尋找轉 JSON 字串成為 物件集合的過程中,碰了不少壁,不過基本上就如同上述的語法,就可以成功的完成囉。

 

透過ObjectDataSource與控制項綁定

設計好了後,就可以把Dao的類別與Function,透過ObjectDataSource的方式,綁到DataSource,並與資料控制項進行綁定,以下就以GridView來當作範例

<asp:GridView ID="gvUV" runat="server" AutoGenerateColumns="False" DataSourceID="odsUV">
    <Columns>
        <asp:BoundField DataField="SiteName" HeaderText="SiteName" SortExpression="SiteName" />
        <asp:BoundField DataField="UVI" HeaderText="UVI" SortExpression="UVI" />
        <asp:BoundField DataField="PublishAgency" HeaderText="PublishAgency" SortExpression="PublishAgency" />
        <asp:BoundField DataField="County" HeaderText="County" SortExpression="County" />
        <asp:BoundField DataField="TWD97Lon" HeaderText="TWD97Lon" SortExpression="TWD97Lon" />
        <asp:BoundField DataField="TWD97Lat" HeaderText="TWD97Lat" SortExpression="TWD97Lat" />
        <asp:BoundField DataField="PublishTime" HeaderText="PublishTime" SortExpression="PublishTime" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="odsUV" runat="server" SelectMethod="GetUVData" TypeName="TestOpenDataUV.UVDao"></asp:ObjectDataSource>

aaa002

 

末記

小喵一開始提到的課程,MVA已經放上去囉,有興趣的朋友可以去參考看看

http://www.microsoftvirtualacademy.com/training-courses/aspnet-web-development-with-azure#mvp32225

^_^

 


以下是簽名:


Microsoft MVP
Visual Studio and Development Technologies
(2005~Now)