C# API取得の流れ(基本)

## ■概要

目的：C#にてAPIを用いて天気情報を取得する。
APIの処理を追って確認する。

今回使用したAPI↓

https://openweathermap.org/api

利用するには登録が必要(無料)。

#### ※2024/12/14追記
今回使用した`Newtonsoft.Json`は現在、推奨されていないため`system.Net.Http.Json`を用いた処理を以下に投稿。

https://qiita.com/Unnmo/items/169d7ba5cc3a888c11a2

**↓参考**

https://qiita.com/SY81517/items/1cf6246dd99869f7b9c5


## ■コード


```c#:Weather.cs
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

class WeatherApp
{
    static async Task Main(string[] args)
    {
        string apiKey = "7b9********************"; // APIキー
        string city = "Tokyo"; // 天気を取得する都市
        string url = $"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={apiKey}&units=metric";

        try
        {
            using (HttpClient client = new HttpClient())
            {
                HttpResponseMessage response = await client.GetAsync(url);
                response.EnsureSuccessStatusCode();

                string responseBody = await response.Content.ReadAsStringAsync();
                //Console.WriteLine("天気データ: ");
                //Console.WriteLine(responseBody);

                //JSONをデシリアライズ
                var weatherData = JsonConvert.DeserializeObject<dynamic>(responseBody);

                // 整形して表示
                Console.WriteLine($"都市: {weatherData.name}");
                Console.WriteLine($"現在の気温: {weatherData.main.temp}°C");
                Console.WriteLine($"体感温度: {weatherData.main.feels_like}°C");
                Console.WriteLine($"天気: {weatherData.weather[0].description}");
                Console.WriteLine($"湿度: {weatherData.main.humidity}%");
                Console.WriteLine($"風速: {weatherData.wind.speed} m/s");
                Console.WriteLine($"雲量: {weatherData.clouds.all}%");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"エラー: {e.Message}");
        }
    }
}
```

## ■詳細

#### 0.必要なライブラリのインポート
```c#:Weather.cs
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
```

`using System;`：基本的なC#の機能（例: Console.WriteLine）を使うためのライブラリ。
`using System.Net.Http;`：HTTP通信を行うためのライブラリ。APIへのリクエストに使用する。
`using System.Threading.Tasks;`：非同期プログラミングをサポートするライブラリ。API呼び出しを非同期で行う。
`using Newtonsoft.Json;`：JSONデータを処理するためのライブラリ。APIのレスポンスをC#のオブジェクトに変換する。

#### 1.APIキーと都市の設定
```c#:Weather.cs
string apiKey = "7b9********************";
string city = "Tokyo";
```

`apiKey`：OpenWeatherMapのAPIキー。APIにアクセスするための認証情報。
`city`：取得したい都市名。


#### 2.URLの組み立て
```c#:Weather.cs
string url = $"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={apiKey}&units=metric";
```
APIのエンドポイント(URL)を作成する。
`{city}`：都市名
`{apiKey}`：APIキー
`units=metric`：温度を摂氏(℃)で取得するように指定。

**・エンドポイントとは？**
APIが提供するサービスや機能にアクセスするためのURL。
≒APIにリクエストを送るための特定のURL

**・エンドポイントの作成方法**
URLは公式ドキュメントに基づいて構築する。
>https://openweathermap.org/current#name
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3844481/42cf196c-e387-2ba5-434c-098a16de9bb8.png)


#### 3.APIリクエスト
```c#:Weather.cs
HttpClient client = new HttpClient()
```
API通信を行うためにインスタンスの生成。


#### 4.APIにリクエストを送信
```c#:Weather.cs
HttpResponseMessage response = await client.GetAsync(url);
```

`HttpResponseMessage`クラスは、「HTTPリクエスト」の結果を格納するクラス。
`GetAsync(url)`を用いて指定したURLにHTTPリクエストを送信し、レスポンスを非同期で受け取る。
`await`を使用することで非同期処理の完了を待つ。

※`HttpResponseMessage`クラスのインスタンスは`client.GetAsync`メソッドによって自動的に生成される
(`HttpResponseMessage`クラスは`client.GetAsync`メソッドとセットで使うイメージ)

#### 5.レスポンスのステータスを確認
```c#:Weather.cs
response.EnsureSuccessStatusCode();
```

サーバーからのレスポンスが成功（例: HTTP 200）であることを確認する。

成功の場合：何も行われず次の処理に進む。
失敗の場合：（例: HTTP 401）例外をスローする。


#### 5.レスポンスの内容を文字列で取得
```c#:Weather.cs
string responseBody = await response.Content.ReadAsStringAsync()
```

`ReadAsStringAsync()`：HttpContent型のデータ(resonse.Content)を非同期的に「文字列」として読み込むメソッド。

APIから送られてきたデータを「文字列」として取得する以下例

```json
//APIから以下のようなJOSONデータが返ってくるとする
{
  "coord": {"lon": 139.6917, "lat": 35.6895},
  "weather": [{"id": 801, "main": "Clouds", "description": "few clouds", "icon": "02d"}],
  "main": {"temp": 20.5, "pressure": 1012, "humidity": 60},
  "name": "Tokyo"
}
```

```plaintext
//ReadAsStringAsync()を使用することで以下のような文字列で取得できる
{"coord":{"lon":139.6917,"lat":35.6895},"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"main":{"temp":20.5,"pressure":1012,"humidity":60},"name":"Tokyo"}
```

#### 6.JSONデータをオブジェクトに変換
```c#:Weather.cs
var weatherData = JsonConvert.DeserializeObject<dynamic>(responseBody);
```

取得したJSON文字列をデシリアライズする。
≒JOSON形式の文字列をC#で扱えるオブジェクト(dynamic型)に変換する。



`JsonConvert`：JSONデータのシリアライズ(オブジェクト→JOSON)やデシリアライズ(JSON→オブジェクト)を扱う。
※利用するには「Newtonsoft.Json」のインストールが必要。

`.DeserializeObject<>`：JSON文字列を指定した型に変換するメソッド。
※dynamic型を使用することで、データ構造が事前にわからない場合でも柔軟にオブジェクトして扱える


#### 7.天気情報を整形して表示
```c#:Weather.cs
Console.WriteLine($"都市: {weatherData.name}");
Console.WriteLine($"現在の気温: {weatherData.main.temp}°C");
Console.WriteLine($"体感温度: {weatherData.main.feels_like}°C");
Console.WriteLine($"天気: {weatherData.weather[0].description}");
Console.WriteLine($"湿度: {weatherData.main.humidity}%");
Console.WriteLine($"風速: {weatherData.wind.speed} m/s");
Console.WriteLine($"雲量: {weatherData.clouds.all}%");
```

取得した天気データを表示する。
`weatherData`オブジェクトから必要なデータを取り出して整形する。