VB.NETとSQLサーバを用いた開発(外部API利用編、前編)
はじめに
この記事では
こちらのAPIを利用して、現在の天気や気温などを表示するFormを作成していきたいと思います。
正直なところ、類似サービス自体はいくらでもあると思うんですが「これを作るために使った知識」自体が、今後の開発に繋がっていくと思います。
今回は、VB.NETが外部APIを叩ける(情報の連携が行える)か確認するところまで。
APIキー利用の準備
まずは、こちらの記事に従って、OpenWetherMap APIのAPIキーを取得してください。
料金プランは、1回に何十件、1日に何回も出力するようなシステムに作り変えない限り、無料枠で大丈夫です。
参考:
APIキーを利用するための、環境変数の準備
コードを書く前に、まずは環境変数を使う準備をします。
環境変数は、コードに直接自分のAPIキーなどを直接書きたくないときや、場合に応じて頻繁に値を書き換える必要がある変数などに使います。
Visual Studio → 「ツール」→「NuGet パッケージ マネージャー」→「パッケージ マネージャー コンソール」
これで、コンソール内に以下のコードを書いてください。
Install-Package DotNetEnv
これで、環境変数を使う下準備が出来ました。

次に、.envファイルを作っていきます。
「~.vbproj」ファイル(.vbファイルの直上)を右クリック→「追加」→新しい項目
これでできたファイルに「.env」と名付けます。

その.envのプロパティの「出力ディレクトリにコピー」で「常にコピーする」を選択するのを忘れずに。

このファイルに、以下のような感じで書き込みます。

例えば、取得したキーが「111111」なら
OPENWEATHER_API_KEY=111111
といった感じです。スペースや""はつけません。
これで、環境変数は完成です。
VB.NETのコード記述
次に、結果表示用のFormを作成します。
それぞれの(Name)は、画像のFormに書かれているとおりに書きましょう。

それが出来たら、コードを記述していきます。
Imports System.Net.Http
Imports System.Text.Json
Imports DotNetEnv
Public Class Form1
Private Async Sub ButtonFetch_Click(sender As Object, e As EventArgs) Handles ButtonFetch.Click
' .env ファイルを読み込む
Env.Load()
Dim apiKey As String = Env.GetString("OPENWEATHER_API_KEY")
MessageBox.Show($"APIキー: {apiKey}")
Dim city As String = TextBoxCity.Text.Trim()
If String.IsNullOrEmpty(city) Then
MessageBox.Show("都市名を入力してください。")
Return
End If
Dim url As String = $"https://api.openweathermap.org/data/2.5/weather?q={Uri.EscapeDataString(city)},JP&units=metric&appid={apiKey}"
Using client As New HttpClient()
Try
Dim resp = Await client.GetAsync(url)
Dim jsonText = Await resp.Content.ReadAsStringAsync()
If Not resp.IsSuccessStatusCode Then
MessageBox.Show($"エラー: {resp.StatusCode}{Environment.NewLine}{jsonText}")
Return
End If
Dim doc = JsonDocument.Parse(jsonText)
Dim weather = doc.RootElement.GetProperty("weather")(0).GetProperty("main").GetString()
Dim temp = doc.RootElement.GetProperty("main").GetProperty("temp").GetDouble()
LabelWeather.Text = $"天気: {weather}"
LabelTemp.Text = $"現在の気温: {temp:F1} ℃"
Catch ex As HttpRequestException
MessageBox.Show($"通信エラー: {ex.Message}")
Catch ex As Exception
MessageBox.Show($"エラー: {ex.Message}")
End Try
End Using
End Sub
End Class
全体像はこんな感じ
順番に解説していきます。
拡張機能
Imports System.Net.Http
Imports System.Text.Json
Imports DotNetEnv
ここでは、使いたい拡張機能等を入力します。
今回は、この3つを使います。
環境変数の設定
まず、Private関数で、ボタンを押した時の挙動を作ります。
今回は、ボタン以外の他に処理がないので、全部この中に動作を作ります。
' .env ファイルを読み込む
Env.Load()
Dim apiKey As String = Env.GetString("OPENWEATHER_API_KEY")
MessageBox.Show($"APIキー: {apiKey}")
ここは、環境変数の設定です。
まずはButtonFetch_Click関数に、これだけ入れて、環境変数の設定が有効か確認してみてください。
ついでにここで、変数apiKey=「環境変数で指定したAPIキー」となっています。
都市名の設定
Dim city As String = TextBoxCity.Text.Trim()
If String.IsNullOrEmpty(city) Then
MessageBox.Show("都市名を入力してください。")
Return
End If
ここは、都市名がTextBoxに記入されたかの確認です。
URLの設定
Dim url As String = $"https://api.openweathermap.org/data/2.5/weather?q={Uri.EscapeDataString(city)},JP&units=metric&appid={apiKey}"
ここは、APIを利用する上でのURLを設定する箇所です。
q={Uri.EscapeDataString(city)},JP
このq=〇〇で、情報を取得するための位置を指定します。
Uri.EscapeDataString()に関しては、文字列をいい感じに処理するくらいの認識で大丈夫で、事実上q=city,JPと書いてるのと同じです。
cityの値は、事前にテキストボックス(TextBoxCity)に書きこんでいるので、そこに「Tokyo」と書き込んだとすると
「q=Tokyo,JP」と書いたことになります。
現在の仕様だと日本専用なので、将来的には
q={Uri.EscapeDataString(city)},{Uri.EscapeDataString(country)}
みたいな拡張が期待されます。
この辺で、SQLと併用する動機が発生しそうですね。
appid={apiKey}は、先程書き込んだAPIキーを入れているだけです。
ということで、そのURLをGoogleChromeで書いてみます。

JSON(データを記述するための構文の1つ)が書いてあるページに遷移できていれば完璧です。
APIからのレスポンス確認
Dim resp = Await client.GetAsync(url)
Dim jsonText = Await resp.Content.ReadAsStringAsync()
If Not resp.IsSuccessStatusCode Then
MessageBox.Show($"エラー: {resp.StatusCode}{Environment.NewLine}{jsonText}")
Return
End If
ここでは、APIからのレスポンスがあるかを確認します。
ここがミスってると(URLの設定がおかしい)=(都市、APIキーのどちらかが間違っている)ことが予想されます。
JSONデータの利用
Dim jsonText = Await resp.Content.ReadAsStringAsync()
(略)
Dim doc = JsonDocument.Parse(jsonText)
Dim weather = doc.RootElement.GetProperty("weather")(0).GetProperty("main").GetString()
Dim temp = doc.RootElement.GetProperty("main").GetProperty("temp").GetDouble()
LabelWeather.Text = $"天気: {weather}"
LabelTemp.Text = $"現在の気温: {temp:F1} ℃"
ここでは、JSONデータを切り分けて、必要な情報をLabelに記述していきます。
Dim doc = JsonDocument.Parse(jsonText)
ここで、JSONデータを細分化します。
Dim weather = doc.RootElement.GetProperty("weather")(0).GetProperty("main").GetString()
Dim temp = doc.RootElement.GetProperty("main").GetProperty("temp").GetDouble()
ここで、その細分化されたデータをどれを使うのかを決めます。
今回は天気と気温の情報がほしいので、それぞれに対応した情報が入手できるようにしていきます。

天気はweather→mainの部分にあり、String型で入手します。
気温もmain→tempの部分にあり、Double型で入手します。
LabelWeather.Text = $"天気: {weather}"
LabelTemp.Text = $"現在の気温: {temp:F1} ℃"
最後に、それぞれのラベルのテキストを、上のように書き換えれば完成です。
なお、気温は小数点1桁までとします。
実際の挙動
ここでは実際の挙動を見ていきます。

TextBoxにTokyoと書き込んだら「ButtonFetch」をクリック

APIキーが書き込まれているかどうかの確認メッセージが出る。これをOK

天気、現在の気温が表示されました。
これにて、APIとの接続が出来ることが確認できました。
今後の展望
今回はAPIとの接続ができればクリアということで、ここまでになりますが、今後修正案があるとしたら、以下のことが挙げられると思います。
・地名を直接TextBoxで記述すると、誤字脱字や、API側の地名データとの表記揺れの問題で記述エラーが発生する可能性が高いので、ComboBoxで記入していきたい。
・それに関連して、ComboBoxに地名を入れるためのテーブルをSQLで作成する。
・検索履歴テーブルを作成し、すでに同条件(地名+日付が一致)で検索されている場合は、APIを叩くのではなく履歴を表示するようにする。(リクエスト数節約のため)
・検索履歴をリセットする。
次回は、上のような機能を実装していければと思います。
後編
Discussion