免費仔開發者的福音!Open吧!!!Data!!!!!

更新於 發佈於 閱讀時間約 15 分鐘

七月到了,天氣也越來越炎熱,已經到了沒有冷氣就不能靜下心來工作的時節,在冷氣房裡雖然舒服,也請別忘記還是要常起來走動,多多補充水分,一直久坐不動對開發職涯來說也是不健康的呀!


這週我們將會來分享一些簡單的資源,作為一個開發者,平常除了維護工作上的專案,你是不是偶爾也會想嘗試一些不一樣的新技術或方向?

我們常常會看到 Apple 官方又發表了一些新的工具或語法可以幫助開發,但卡在專案支援的版本而無法使用,等到真的可以應用在產品上時,可能已經又過了兩三年。因此對開發者來說,Side Project 非常的重要!你可以按照自己的步調來學習新的技術,並且在專案中實際練習與應用,甚至上架到 App Store 讓世界看見你的作品!但是獨立開發並不是一件容易的事,如果你想要做一個串接 API 來顯示資料的 App,不像在公司裡有後端工程師,可以幫你處理資料的串接,你必須要想辦法自己完成。這時候,Open Data 就派上用場了!

這篇文章將介紹台灣兩個超實用的開放資料平台:「政府資料開放平台」「Cafe Nomad」,透過平台提供的接口和資料,來實作一個簡單的 API Service。

Open Data 是指政府或機構將資料開放給公眾使用,通常以開放授權的方式提供,讓任何人都可以自由使用、重製、散布、改作等。


資料來源 - 政府資料開放平台、Cafe Nomad

在動手寫程式碼之前,我們先了解一下這兩個平台。

政府資料開放平台

政府資料開放平台是台灣政府根據《政府資訊公開法》所建立的資料開放平台,自 2013 年起開始服務,提供超過 100 個單位、超過 100,000 筆的資料,涵蓋了天氣、交通、人口統計等各種資訊。

舉例來說,我們想要取得空氣品質的資料,可以點開 空氣品質指標(AQI) 這個資料集,可以看到主要欄位說明、下載網址(以這個範例來說提供了 JSON、CSV、XML 三種格式)、提供機關、聯絡人等等資訊。

以大部分 iOS 開發者來說,最常使用的格式就是 JSON,因此我們點擊 JSON 格式的按鈕,便可以看到資料內容。

你可以在平台上找到各式各業政府整理後公開的資料,串接到你的 App 中,再補上顯示邏輯,就可以完成一個簡單的 App。

Cafe Nomad

Cafe Nomad 是由工程師 尤川豪 在2016年開發的咖啡廳資訊平台,提供全台咖啡廳資訊,包括咖啡廳的地址、電話、營業時間等資訊。

專案是全開源,可以從官網上連到 GitHub 來查看。

雖然目前專案看起來已經進入維護狀態,雖然有看到宣告要做 v2.0 的更新,也已經有測試站,但看起來進度就停在這邊,希望有機會能看到作者更新。

但就算這樣還是別擔心,舊有的 API 仍然可以正常呼叫使用,因此要作為開發練習的話,還是沒有問題。

網站上面也提供了透過這個服務所建立的 App 清單,並且開放新增,如果你也透過他們的 API 完成了自己的作品,可以到 這邊 點擊表單來分享。

檢查了一下大部分的 App 都已經下架了,應該也是當初的 Developer 的練習作品。


實作

既然咖啡是工程師工作上不可或缺的夥伴之一,那麼接下來,我們便將串接 Cafe Nomad 的 API,實作一個 API Service,並將他封裝在 Swift Package Manager 中,方便在其他專案中使用。

建立專案

首先,我們先建立一個新的 Swift Package Manager 專案,並且選擇 Swift Package Manager 作為專案類型。

swift package init --type library --name CafeNomadService

如果不熟悉 CLI,也可以使用 Xcode 來建立新的 Swift Package Manager。

根據 Cafe Nomad API V1.2 的文件,因為基本上只有開放兩支 API(All Cafes, Cafes by city),並不複雜,我們先根據資料欄位來建立對應的 Model。

先在 Sources/CafeNomadService 底下建立一個 Models 資料夾,並且建立一個 Cafe.swift 檔案,來存放 Cafe 的資料。

public struct Cafe: Codable, Sendable {
public let id: String
public let name: String
public let wifi: Double
public let seat: Double
public let quiet: Double
public let tasty: Double
public let cheap: Double
public let music: Double
public let address: String
public let latitude: String
public let longitude: String
public let url: String
public let limitedTime: LimitedTime?
public let socket: Socket?
public let standingDesk: StandingDesk?
public let mrt: String?
public let openTime: String?

// Codable 的實作
}

// 是否有限時
public enum LimitedTime: String, Codable, Sendable {
case yes = "yes" // 一律有限時
case maybe = "maybe" // 看情況,假日或客滿限時
case no = "no" // 一律不限時
}

// 是否有插座
public enum Socket: String, Codable, Sendable {
case yes = "yes" // 很多
case maybe = "maybe" // 還好,看座位
case no = "no" // 很少
}

// 是否有站立座位
public enum StandingDesk: String, Codable, Sendable {
case yes = "yes" // 有些座位可以
case no = "no" // 無法
}

我們將 LimitedTimeSocketStandingDesk 三個資料欄位透過 enum 來表示,方便後續的判斷。

至此,簡單的 Cafe Model 就完成了。

接下來,就是來實作 API 的串接。

我們將使用 URLSession,透過 Concurrency 的方式來實作非同步的 API 串接。

先想像我們希望讓使用這個 Package 的開發者,可以用什麼樣的方式來接資料:

let cafeService = CafeNomadService()

let cafes = try await cafeService.fetchAllCafes()
let cafesInTaipei = try await cafeService.fetchCafes(for: "taipei")

根據文件,我們可以透過兩支 API 來取得全部的咖啡廳資料,或者特定城市的咖啡廳資料。

我們這邊保留未來的擴充性,將 city 參數使用 String,如果開發者有需要,也可以自行建立一個 enum 來方便管理。

關於enum,可以參考這篇:

已經定義好 Model 和 API 接口的話,接下來就是實作 CafeNomadService 的內容了:

public final class CafeNomadService: Sendable {

private let baseURL = "https://cafenomad.tw/api/v1.2/cafes"
private let session: URLSession

public init(session: URLSession = .shared) {
self.session = session
}

// MARK: - Public Methods

/// 取得全台灣咖啡廳資料
@available(macOS 12.0, iOS 15.0, watchOS 8.0, *)
public func fetchAllCafes() async throws -> [Cafe] {
// ...
}

/// 取得指定城市咖啡廳資料
/// - Parameter city: 城市名稱 (例如: "taipei", "hsinchu", "kaohsiung")
@available(macOS 12.0, iOS 15.0, watchOS 8.0, *)
public func fetchCafes(for city: String) async throws -> [Cafe] {
// ...
}
}

因為兩個 API 的網址都相同,只是參數不同,因此我們可以將 fetchCafes 方法抽離出來,讓兩個 API 共用。

而且因為 Method 都是 GET,因此我們對 URLSession 也不必額外再多做設定。

  private func fetchCafes(from url: URL) async throws -> [Cafe] {
let (data, response) = try await session.data(from: url)

guard let httpResponse = response as? HTTPURLResponse else {
throw CafeNomadError.invalidResponse
}

guard 200...299 ~= httpResponse.statusCode else {
throw CafeNomadError.httpError(httpResponse.statusCode)
}

do {
let decoder = JSONDecoder()
return try decoder.decode([Cafe].self, from: data)
} catch {
throw CafeNomadError.decodingError(error)
}
}

接下來,我們就可以實作 fetchAllCafes 和 fetchCafes 方法了。

  /// 取得全台灣咖啡廳資料
public func fetchAllCafes() async throws -> [Cafe] {
guard let url = URL(string: baseURL) else {
throw CafeNomadError.invalidURL(baseURL)
}
return try await fetchCafes(from: url)
}

/// 取得指定城市咖啡廳資料
/// - Parameter city: 城市名稱 (例如: "taipei", "hsinchu", "kaohsiung")
public func fetchCafes(for city: String) async throws -> [Cafe] {
let urlString = "\(baseURL)/\(city)"
guard let url = URL(string: urlString) else {
throw CafeNomadError.invalidURL(urlString)
}
return try await fetchCafes(from: url)
}

這樣就完成了一個簡單的 API Service!可以用它來串接 Cafe Nomad 的 API,並且在 App 中使用。

如果有需要的話,我把這次的專案放在 GitHub 上,有興趣的話可以直接拿來使用。


CafeNomad 是我從以前就很喜歡的服務,希望透過這次的介紹,讓更多人認識她,也期待有開發夥伴能繼續使用他們的服務,創造更多新的 App。

當然也還有政府資料開放平台,上面的各種資料非常值得大家去研究,練習技術之餘還能幫助民眾更加了解台灣政府資訊。

以上,就是這次分享的內容,希望對你有幫助!

喜歡這篇文章,或者覺得對你有幫助的話,可以分享給需要的人,也歡迎留言討論!我們下次再見!


參考資料

本篇文章完成的專案使用 Cursor IDE 協作完成。


留言
avatar-img
留言分享你的想法!
avatar-img
Rice把拔的生活與開發筆記
0會員
17內容數
這裡是我的開發與生活筆記。 分享iOS開發經驗、教學技巧,也記錄生活中的點滴與觀察。 偶爾來點評論,輕鬆聊聊技術與日常。
2025/06/18
WWDC25 心得分享:iOS開發者觀點,包含對 Apple Intelligence、Shortcuts、Siri、Spotlight 等功能更新的個人看法,以及 Liquid Glass 等新功能的體驗,並推薦一些值得關注的開發者相關 Session。
Thumbnail
2025/06/18
WWDC25 心得分享:iOS開發者觀點,包含對 Apple Intelligence、Shortcuts、Siri、Spotlight 等功能更新的個人看法,以及 Liquid Glass 等新功能的體驗,並推薦一些值得關注的開發者相關 Session。
Thumbnail
2025/06/11
將中華職棒的例行賽紀錄,從定義打擊結果、球員資料到組合成局數、比賽狀態,一步步地將棒球規則轉換成程式碼。
2025/06/11
將中華職棒的例行賽紀錄,從定義打擊結果、球員資料到組合成局數、比賽狀態,一步步地將棒球規則轉換成程式碼。
2025/06/04
WWDC25 即將到來!有什麼值得我們期待和關注的呢?
Thumbnail
2025/06/04
WWDC25 即將到來!有什麼值得我們期待和關注的呢?
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
自由接案好像很自由、容易,卻需要點方向的指引,希望這篇的分享能給予你一些幫助。
Thumbnail
自由接案好像很自由、容易,卻需要點方向的指引,希望這篇的分享能給予你一些幫助。
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
Thumbnail
本文檔介紹了在Swift中使用套件的詳細方法,包括如何引用第三方套件和自定義模組,如何創建自定義套件,以及一些常見的Swift套件。這些套件可以幫助開發者快速添加功能到項目中,提高開發效率和程式碼品質。
Thumbnail
本文檔介紹了在Swift中使用套件的詳細方法,包括如何引用第三方套件和自定義模組,如何創建自定義套件,以及一些常見的Swift套件。這些套件可以幫助開發者快速添加功能到項目中,提高開發效率和程式碼品質。
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
需求情境: 在設計畫面時,資料來源是後台的 api,每一次畫面細節的修修改改,都會觸發 Xcode Preview 程序,導致不斷呼叫後台。此時若資料結構和大小都具有一定規模,就會導致效率低落,不斷等待,且消耗伺服器資源甚鉅。 解決方案: 將後台傳回的資料以檔案形式暫存在本地端,每次 pr
Thumbnail
需求情境: 在設計畫面時,資料來源是後台的 api,每一次畫面細節的修修改改,都會觸發 Xcode Preview 程序,導致不斷呼叫後台。此時若資料結構和大小都具有一定規模,就會導致效率低落,不斷等待,且消耗伺服器資源甚鉅。 解決方案: 將後台傳回的資料以檔案形式暫存在本地端,每次 pr
Thumbnail
這篇文章描述了作者從兼職開發轉為全職開發的過程,並分享了從混進學界指日可待的積極態度。作者也提及自己在專案製作與個人生活上的矛盾與感想,最後分享了專案管理和敏捷開發相關的文章與影片。
Thumbnail
這篇文章描述了作者從兼職開發轉為全職開發的過程,並分享了從混進學界指日可待的積極態度。作者也提及自己在專案製作與個人生活上的矛盾與感想,最後分享了專案管理和敏捷開發相關的文章與影片。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
先前幾篇筆記介紹了網路請求,瀏覽器儲存資料的方式,那麼實務上,前端最常需要發送網路請求的時候,就是透過呼叫 API,去向後端工程師發送/請求資料,所以今天來記錄什麼是 API吧!
Thumbnail
先前幾篇筆記介紹了網路請求,瀏覽器儲存資料的方式,那麼實務上,前端最常需要發送網路請求的時候,就是透過呼叫 API,去向後端工程師發送/請求資料,所以今天來記錄什麼是 API吧!
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News