私は最近プログラミングにはまっていて、よくJSONデータを扱います。
C# .NETでJSONをデシリアライズするときはいつもこれを使っていました。
Newtonsoft.Json.JsonConvert.DeserializeObject<クラス>(JSONデータ);
しかし、これでは対応できないようなデータがあります。それが、気象庁のアメダスデータです。
{
{
"11001": {
"temp": [
-1.1,
0
],
"humidity": [
100,
0
],
"snow1h": [
0,
null
],
"snow6h": [
0,
null
],
"snow12h": [
0,
null
],
"snow24h": [
0,
null
],
"sun10m": [
0,
0
],
"sun1h": [
0.0,
0
],
"precipitation10m": [
0.0,
0
],
"precipitation1h": [
0.0,
0
],
"precipitation3h": [
0.0,
0
],
"precipitation24h": [
0.5,
0
],
"windDirection": [
4,
0
],
"wind": [
1.2,
0
]
}
}
※データは、”https://www.jma.go.jp/bosai/amedas/data/map/”最終更新時刻(yyyyMMddHHmmss)”.json”でアクセスすることが可能です。最終更新時刻はhttps://www.jma.go.jp/bosai/amedas/data/latest_time.txtで取得できます。
観測点によってJSONのKeyが異なるのでクラスにするとえらいことになります。
これでは観測点の情報を処理するときとっても面倒ですよね。
var amedas = Newtonsoft.Json.JsonConvert.DeserializeObject<クラス>(JSONデータ);
List<double> wind = new();
wind.Add(amedas._11001.wind[0]);
wind.Add(amedas._11016.wind[0]);
wind.Add(amedas._11046.wind[0]);
wind.Add(amedas._11061.wind[0]);
続く....
そこで、keyが定まっていないJSONをデシリアライズする方法について書こうと思います。
どうやってkeyが定まっていないJSONをデシリアライズするのか
Newtonsoft.JsonでJSONをデシリアライズする方法はJsonConvert.DeserializeObject以外にもあります。それが、JObject.Parseです。
使い方
JObject amedas = JObject.Parse(JSONデータ);
これをうまく使うことによってデシリアライズしていきます。
情報を取得
まずは情報の取得から行きましょう。
string latest_Time = await client.GetStringAsync("https://www.jma.go.jp/bosai/amedas/data/latest_time.txt");
DateTime dateTime = DateTime.Parse(latest_Time);
latest_time.txtをDateTimeにします。
string url = "https://www.jma.go.jp/bosai/amedas/data/map/" + dateTime.ToString("yyyyMMddHHmmss") + ".json";
string amedas_Data = await client.GetStringAsync(url);
最終更新時刻をURLに入れて、GetStringAsyncでJSONデータを取得します。
これでJSONデータの取得は完了です。
デシリアライズ
次に、本命のデシリアライズをしていきます。今回は風速のみを取得していきます。(ほかの部分でも使用できるよう、クラスにはそのほかのものも入れています。)
JObject amedas = JObject.Parse(amedas_Data);
var amedas_List = new List<JMA_amedas>();
JObjectでパースした後、情報を入れるリストを作ります。
foreach (var pair in amedas)
{
}
このforeachのpairは一つの観測点の情報です。
JValue? wind_content = null;
wind_content = (JValue?)pair.Value?[key: "wind"]?[0];
JValueを新たに作り、その中にwindの中身を入れます。この時、観測点によっては風速の情報がないので、?演算子をつけておきましょう。
※pairのKeyはpair.Key、Valueはpair.Valueとなっています。Valueは観測点の情報です。
if (wind_content?.Value != null)
{
amedas_List.Add(new());
amedas_List[amedas_List.Count - 1].id = Convert.ToInt32(pair.Key);
amedas_List[amedas_List.Count - 1].wind = (double)wind_content;
}
もし、valueがnullでないならアメダスのリストに新しいものを追加して、末尾のidにpairのKey、windにwind_contentを入れます。
最後に、風速順にしたいので、OrderByDescendingを使います。
var amedas_Ranking = amedas_List.OrderByDescending(x => x.wind).ToList();
foreach(var content in amedas_Ranking)
{
Console.WriteLine(content.id);
Console.WriteLine(content.wind);
}
完成です!実行すると、このようになります。
風速順になって、しっかり取得できていました。
なお、今回のサンプルコードはGitHubに置いておきます。
LifeOTE/JMASample: 気象庁のサイトからアメダスを取得するサンプル。 (github.com)
今回はここまでです。最後までご覧いただきありがとうございました。
コメント