天気予報APIからリアル天気情報を取得する

2025年8月14日

本プログラムは、C#とWindows Formsを用いて開発されたシンプルな天気予報チェックアプリケーションです。ユーザーがコンボボックスから都市を選択すると、指定された都市の天気情報を取得し、アプリケーション上に表示します。天気情報は「気象庁の非公式API」を利用して取得します。

フリーの天気リアル情報サーバ(JSONで取得可能)

自分で、頑張って取得アプリを実現してみましょう!!

NewtonソフトのJsonコンバータを採用しているコードからSystem.Text.Jsonへの更新作業手順概要をベースにしてます

Newtonソフト版のJsonコンバータでは、同じコードになりませんが地域コードをサーバのものを採用、分析するためのクラスをサーバのものに合わせることで対応できます

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Windows.Forms;

namespace WeatherChecker
{
    public partial class Form1 : Form
    {
        // 都市名とコードを紐付けるDictionary
        private readonly Dictionary<string, string> cityNames;

        public Form1()
        {
            InitializeComponent();

            // 都市名と都市コードの辞書を初期化
            cityNames = new Dictionary<string, string>
            {
                { "東京都", "400040" },
                { "大阪府", "1" },
                { "愛知県", "2" },
                { "福岡県", "10" }
            };

            // 都市名をComboBoxに追加
            foreach (KeyValuePair<string, string> data in cityNames)
            {
                areaBox.Items.Add(data.Key);
            }
        }

        // 都市名が選択されたときの処理
        private void CitySelected(object sender, EventArgs e)
        {
            // 天気情報サービスにアクセス
            string cityCode = cityNames[areaBox.Text];
            string url = $"https://weather.tsukumijima.net/api/forecast/city/{cityCode}";

            HttpClient client = new HttpClient();
            string result = client.GetStringAsync(url).Result;

            // 天気情報からアイコンのURLを取り出す
            var weatherInfo = JsonConvert.DeserializeObject<WeatherInfo>(result);
            var data = weatherInfo.description.bodyText;

            // 結果をtextBox1に表示したい場合
            // textBox1.Text = data;
        }

        // 終了メニューがクリックされたときの処理
        private void ExitMenuClicked(object sender, EventArgs e)
        {
            // フォームを閉じる
            this.Close();
        }

        public class WeatherInfo
        {
            public DateTime publicTime { get; set; }
            public string publicTimeFormatted { get; set; }
            public string publishingOffice { get; set; }
            public string title { get; set; }
            public string link { get; set; }
            public Description description { get; set; }
            public Forecast[] forecasts { get; set; }
            public Location location { get; set; }
            public Copyright copyright { get; set; }
        }

        public class Description
        {
            public DateTime publicTime { get; set; }
            public string publicTimeFormatted { get; set; }
            public string headlineText { get; set; }
            public string bodyText { get; set; }
            public string text { get; set; }
        }

        public class Location
        {
            public string area { get; set; }
            public string prefecture { get; set; }
            public string district { get; set; }
            public string city { get; set; }
        }

        public class Copyright
        {
            public string title { get; set; }
            public string link { get; set; }
            public Image image { get; set; }
            public Provider[] provider { get; set; }
        }

        public class Image
        {
            public string title { get; set; }
            public string link { get; set; }
            public string url { get; set; }
            public int width { get; set; }
            public int height { get; set; }
        }

        public class Provider
        {
            public string link { get; set; }
            public string name { get; set; }
            public string note { get; set; }
        }

        public class Forecast
        {
            public string date { get; set; }
            public string dateLabel { get; set; }
            public string telop { get; set; }
            public Detail detail { get; set; }
            public Temperature temperature { get; set; }
            public Chanceofrain chanceOfRain { get; set; }
            public Image1 image { get; set; }
        }

        public class Detail
        {
            public string weather { get; set; }
            public string wind { get; set; }
            public string wave { get; set; }
        }

        public class Temperature
        {
            public Min min { get; set; }
            public Max max { get; set; }
        }

        public class Min
        {
            public string celsius { get; set; }
            public string fahrenheit { get; set; }
        }

        public class Max
        {
            public string celsius { get; set; }
            public string fahrenheit { get; set; }
        }

        public class Chanceofrain
        {
            public string T00_06 { get; set; }
            public string T06_12 { get; set; }
            public string T12_18 { get; set; }
            public string T18_24 { get; set; }
        }

        public class Image1
        {
            public string title { get; set; }
            public string url { get; set; }
            public int width { get; set; }
            public int height { get; set; }
        }
    }
}
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WeatherChecker
{
    public partial class Form1 : Form
    {
        // 都市名とコードを紐付けるDictionary
        private readonly Dictionary<string, string> cityNames;

        // HttpClient は使い回す(ソケット枯渇を防ぐ)
        private static readonly HttpClient http = new HttpClient
        {
            Timeout = TimeSpan.FromSeconds(10) // タイムアウト(必要に応じて調整)
        };

        public Form1()
        {
            InitializeComponent();

            // 都市名と都市コードの辞書を初期化
            cityNames = new Dictionary<string, string>
            {
                { "東京都", "400040" },
                { "大阪府", "270000" }, // 実コードに差し替え推奨(例)
                { "愛知県", "230010" }, // 実コードに差し替え推奨(例)
                { "福岡県", "400010" }  // 実コードに差し替え推奨(例)
            };

            // 都市名をComboBoxに追加
            foreach (KeyValuePair<string, string> data in cityNames)
            {
                areaBox.Items.Add(data.Key);
            }

            // できれば UI 側でイベント配線:areaBox.SelectedIndexChanged += CitySelected;
        }

        // 都市名が選択されたときの処理(非同期)
        private async void CitySelected(object sender, EventArgs e)
        {
            // 選択値検証
            if (string.IsNullOrWhiteSpace(areaBox.Text))
            {
                ShowError("都市名が選択されていません。");
                return;
            }

            if (!cityNames.TryGetValue(areaBox.Text, out string cityCode) || string.IsNullOrWhiteSpace(cityCode))
            {
                ShowError("都市コードが見つかりません。選択を確認してください。");
                return;
            }

            string url = $"https://weather.tsukumijima.net/api/forecast/city/{cityCode}";

            // フェッチ中のUI状態
            var prevCursor = this.Cursor;
            this.Cursor = Cursors.WaitCursor;
            areaBox.Enabled = false;

            // キャンセルが欲しければフォームに CancellationTokenSource を持たせる設計も可
            using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(12)))
            {
                try
                {
                    // User-Agent を明示(API によっては必須になることがある)
                    if (!http.DefaultRequestHeaders.UserAgent.TryParseAdd("WeatherChecker/1.0"))
                    {
                        // 無視してよいが、必要ならログ
                    }

                    using (var resp = await http.GetAsync(url, cts.Token).ConfigureAwait(true))
                    {
                        // ステータスコード検証
                        resp.EnsureSuccessStatusCode();

                        string json = await resp.Content.ReadAsStringAsync().ConfigureAwait(true);

                        // JSON をオブジェクトへ
                        var weatherInfo = JsonConvert.DeserializeObject<WeatherInfo>(json);
                        if (weatherInfo == null || weatherInfo.description == null)
                        {
                            ShowError("天気データの形式が予期しないものでした。");
                            return;
                        }

                        string data = weatherInfo.description.bodyText ?? weatherInfo.description.text ?? "(説明なし)";

                        // 結果表示(必要に応じて UI を更新)
                        // textBox1.Text = data; // ←使用する場合はコメント解除
                        MessageBox.Show(this, data, "天気情報", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                catch (TaskCanceledException)
                {
                    ShowError("通信がタイムアウトしました。ネットワーク環境を確認して再試行してください。");
                }
                catch (HttpRequestException ex)
                {
                    ShowError($"通信エラーが発生しました: {ex.Message}");
                }
                catch (JsonException ex)
                {
                    ShowError($"データの読み取りに失敗しました(JSON形式エラー): {ex.Message}");
                }
                catch (Exception ex)
                {
                    // 想定外の例外も握りつぶさず通知
                    ShowError($"不明なエラーが発生しました: {ex.Message}");
                }
                finally
                {
                    // UI 復帰
                    areaBox.Enabled = true;
                    this.Cursor = prevCursor;
                }
            }
        }

        // 終了メニューがクリックされたときの処理
        private void ExitMenuClicked(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ShowError(string message)
        {
            // textBox1 にも出したい場合はコメント解除
            // textBox1.Text = message;
            MessageBox.Show(this, message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        // 以降は API レスポンス用モデル
        public class WeatherInfo
        {
            public DateTime publicTime { get; set; }
            public string publicTimeFormatted { get; set; }
            public string publishingOffice { get; set; }
            public string title { get; set; }
            public string link { get; set; }
            public Description description { get; set; }
            public Forecast[] forecasts { get; set; }
            public Location location { get; set; }
            public Copyright copyright { get; set; }
        }

        public class Description
        {
            public DateTime publicTime { get; set; }
            public string publicTimeFormatted { get; set; }
            public string headlineText { get; set; }
            public string bodyText { get; set; }
            public string text { get; set; }
        }

        public class Location
        {
            public string area { get; set; }
            public string prefecture { get; set; }
            public string district { get; set; }
            public string city { get; set; }
        }

        public class Copyright
        {
            public string title { get; set; }
            public string link { get; set; }
            public Image image { get; set; }
            public Provider[] provider { get; set; }
        }

        public class Image
        {
            public string title { get; set; }
            public string link { get; set; }
            public string url { get; set; }
            public int width { get; set; }
            public int height { get; set; }
        }

        public class Provider
        {
            public string link { get; set; }
            public string name { get; set; }
            public string note { get; set; }
        }

        public class Forecast
        {
            public string date { get; set; }
            public string dateLabel { get; set; }
            public string telop { get; set; }
            public Detail detail { get; set; }
            public Temperature temperature { get; set; }
            public Chanceofrain chanceOfRain { get; set; }
            public Image1 image { get; set; }
        }

        public class Detail
        {
            public string weather { get; set; }
            public string wind { get; set; }
            public string wave { get; set; }
        }

        public class Temperature
        {
            public Min min { get; set; }
            public Max max { get; set; }
        }

        public class Min
        {
            public string celsius { get; set; }
            public string fahrenheit { get; set; }
        }

        public class Max
        {
            public string celsius { get; set; }
            public string fahrenheit { get; set; }
        }

        public class Chanceofrain
        {
            public string T00_06 { get; set; }
            public string T06_12 { get; set; }
            public string T12_18 { get; set; }
            public string T18_24 { get; set; }
        }

        public class Image1
        {
            public string title { get; set; }
            public string url { get; set; }
            public int width { get; set; }
            public int height { get; set; }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Windows.Forms;

namespace WeatherChecker
{
    public partial class Form1 : Form
    {
        private Dictionary<string, string> cityNames;

        public Form1()
        {
            InitializeComponent();

            cityNames = new Dictionary<string, string>
            {
                { "東京都", "400040" },
                { "大阪府", "1" },
                { "愛知県", "2" },
                { "福岡県", "10" }
            };

            foreach (KeyValuePair<string, string> data in cityNames)
            {
                areaBox.Items.Add(data.Key);
            }
        }

        private async void CitySelected(object sender, EventArgs e)
        {
            try
            {
                // 天気情報サービスにアクセスする
                string cityCode = cityNames[areaBox.Text];
                string url = $"https://weather.tsukumijima.net/api/forecast/city/{cityCode}";

                using (HttpClient client = new HttpClient())
                {
                    string result = await client.GetStringAsync(url);

                    // 天気情報からアイコンのURLを取り出す
                    WeatherInfo weatherInfo = JsonSerializer.Deserialize<WeatherInfo>(result);
                    var data = weatherInfo.description.bodyText;
                  //  textBox1.Text = data;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ExitMenuClicked(object sender, EventArgs e)
        {
            // フォームを閉じる
            this.Close();
        }

        public class WeatherInfo
        {
            public DateTime publicTime { get; set; }
            public string publicTimeFormatted { get; set; }
            public string publishingOffice { get; set; }
            public string title { get; set; }
            public string link { get; set; }
            public Description description { get; set; }
            public Forecast[] forecasts { get; set; }
            public Location location { get; set; }
            public Copyright copyright { get; set; }
        }

        public class Description
        {
            public DateTime publicTime { get; set; }
            public string publicTimeFormatted { get; set; }
            public string headlineText { get; set; }
            public string bodyText { get; set; }
            public string text { get; set; }
        }

        public class Location
        {
            public string area { get; set; }
            public string prefecture { get; set; }
            public string district { get; set; }
            public string city { get; set; }
        }

        public class Copyright
        {
            public string title { get; set; }
            public string link { get; set; }
            public Image image { get; set; }
            public Provider[] provider { get; set; }
        }

        public class Image
        {
            public string title { get; set; }
            public string link { get; set; }
            public string url { get; set; }
            public int width { get; set; }
            public int height { get; set; }
        }

        public class Provider
        {
            public string link { get; set; }
            public string name { get; set; }
            public string note { get; set; }
        }

        public class Forecast
        {
            public string date { get; set; }
            public string dateLabel { get; set; }
            public string telop { get; set; }
            public Detail detail { get; set; }
            public Temperature temperature { get; set; }
            public Chanceofrain chanceOfRain { get; set; }
            public Image1 image { get; set; }
        }

        public class Detail
        {
            public string weather { get; set; }
            public string wind { get; set; }
            public string wave { get; set; }
        }

        public class Temperature
        {
            public Min min { get; set; }
            public Max max { get; set; }
        }

        public class Min
        {
            public string celsius { get; set; }
            public string fahrenheit { get; set; }
        }

        public class Max
        {
            public string celsius { get; set; }
            public string fahrenheit { get; set; }
        }

        public class Chanceofrain
        {
            public string T00_06 { get; set; }
            public string T06_12 { get; set; }
            public string T12_18 { get; set; }
            public string T18_24 { get; set; }
        }

        public class Image1
        {
            public string title { get; set; }
            public string url { get; set; }
            public int width { get; set; }
            public int height { get; set; }
        }
    }
}
訪問数 149 回, 今日の訪問数 1回