例、OpenWeather API
JSONを受ける構造体を用意する
Codableを継承させた構造体を用意する。
・変数名はJSONのキーと文字列を合わせる。
・型も受け取れるように合わせる
・階層化している場合は同じく構造体を階層化させて合わせる。
・リストView等で使う場合は Identifiable も継承させる。
→その場合は var id: UUID { UUID() } 等を一番上位の構造体で宣言しておく。
送られてくるJSON
|
1 |
'{"coord":{"lon":141.6809,"lat":45.4176},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"base":"stations","main":{"temp":290.44,"feels_like":290.29,"temp_min":290.44,"temp_max":290.44,"pressure":1006,"humidity":79,"sea_level":1006,"grnd_level":1004},"visibility":10000,"wind":{"speed":9.71,"deg":23,"gust":10.7},"clouds":{"all":73},"dt":1757809226,"sys":{"country":"JP","sunrise":1757794208,"sunset":1757839685},"timezone":32400,"id":2127515,"name":"Wakkanai","cod":200}' |
Swift側で用意する構造体
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import Foundation struct WeatherResponse: Codable { let coord: Coord let weather: [Weather] let base: String let main: Main let visibility: Int let wind: Wind let clouds: Clouds let dt: Int let sys: Sys let timezone: Int let id: Int let name: String let cod: Int } struct Coord: Codable { let lon: Double let lat: Double } struct Weather: Codable { let id: Int let main: String let description: String let icon: String } struct Main: Codable { let temp: Double let feels_like: Double let temp_min: Double let temp_max: Double let pressure: Int let humidity: Int let sea_level: Int? let grnd_level: Int? } struct Wind: Codable { let speed: Double let deg: Int let gust: Double? } struct Clouds: Codable { let all: Int } struct Sys: Codable { let country: String let sunrise: Int let sunset: Int } |
デコードの例
JSONとキーの文字列、構造が合っていないと失敗します。
受け取る個数は合っていなくても問題なく受け取れます、例API側の項目が5つ、アプリ側の項目が3つでもちゃんとデコードに成功します。
受け取りたいデータだけ宣言すればOK。
コードのURLは一度違うサーバーを経由している想定です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import Foundation func fetchWeather() { guard let url = URL(string: "https://yourdomain.com/api-proxy.php?endpoint=weather?q=Wakkanai&units=metric") else { return } URLSession.shared.dataTask(with: url) { data, response, error in if let data = data { do { let weather = try JSONDecoder().decode(WeatherResponse.self, from: data) print("都市名: \(weather.name)") print("気温: \(weather.main.temp)") print("天気: \(weather.weather.first?.description ?? "")") } catch { print("デコード失敗: \(error)") } } }.resume() } |
APIリクエスト時のトークン取得方法(必要ある時)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
func fetchToken() async throws -> String { let url = URL(string: "https://example.com/wp-json/tsuriba/v1/get-token")! var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = " キー ".data(using: .utf8) //JWTのトークンをもらう時のキーを入れる request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") let (data, _) = try await URLSession.shared.data(for: request) let result = try JSONDecoder().decode(TokenResponse.self, from: data) return result.token } struct TokenResponse: Codable { let token: String let expires_in: Int } |
取得した token を UserDefaultsやKeychainに保存しておき、
その後のAPIリクエストでは Authorization: Bearer <token> を付与してアクセスします。
APIリクエスト時のトークン付与方法(必要ある時)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
func fetchWeather(token: String) async throws -> WeatherResponse { let url = URL(string: "https://example.com/wp-json/tsuriba/v1/weather")! var request = URLRequest(url: url) request.httpMethod = "GET" // Authorization ヘッダに Bearer トークンを付与 request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") //ここ let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw URLError(.badServerResponse) } return try JSONDecoder().decode(WeatherResponse.self, from: data) } struct WeatherResponse: Codable { let temp: Double let wind: String let condition: String } |

コメント