C# における JSON データの解析方法比較と最適な実装

System.Text.Json を用いた JSON データの解析とその最適化 ~


1. はじめに

C# では、外部 API から取得した JSON データを解析し、アプリケーション内で活用することが一般的です。本資料では、以下の2つの方法を比較し、より最適な実装を提案します。

  1. JsonDocument を使用した JSON 解析
  2. JsonSerializer.Deserialize<T>() を使用した JSON 解析

System.Text.Json を活用し、よりシンプルで拡張性の高いコードの実装を目指します。


2. JSON の解析方法

2.1. JsonDocument を使用した JSON の解析

実装方法

using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        string url = "https://example.com/api/weather";
        HttpClient client = new HttpClient();
        string result = await client.GetStringAsync(url);

        using (JsonDocument doc = JsonDocument.Parse(result))
        {
            if (doc.RootElement.TryGetProperty("url", out JsonElement urlElement))
            {
                Console.WriteLine("天気アイコンのURL: " + urlElement.GetString());
            }
        }
    }
}

特徴

  • JsonDocument.Parse(result) を用いて JSON を解析。
  • TryGetProperty("url", out JsonElement urlElement) でプロパティの有無を確認。
  • JsonElementstring に変換して取得。

メリット

✅ 部分的にデータを取得する際に有効。
✅ JSON 内の特定のキーをチェックすることが可能。

デメリット

TryGetProperty を使うためコードが冗長になりやすい。
❌ プロパティの数が増えると管理が煩雑になる。
❌ JSON の構造変更に対する柔軟性が低い。


2.2. JsonSerializer.Deserialize<T>() を使用した JSON の解析

実装方法

using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

public class WeatherResponse
{
    public string Url { get; set; } = string.Empty;
}

public class Program
{
    public static async Task Main()
    {
        string url = "https://example.com/api/weather";
        HttpClient client = new HttpClient();
        string result = await client.GetStringAsync(url);

        // JSON をクラスにマッピング
        WeatherResponse? weatherData = JsonSerializer.Deserialize<WeatherResponse>(result);

        if (weatherData != null && !string.IsNullOrEmpty(weatherData.Url))
        {
            Console.WriteLine("天気アイコンのURL: " + weatherData.Url);
        }
    }
}

特徴

  • JsonSerializer.Deserialize<T>() を使用して JSON を WeatherResponse クラスに変換。
  • プロパティが public string Url { get; set; } に自動でマッピングされる。
  • null チェックのみでエラーハンドリングが可能。

メリット

コードがシンプルで可読性が高い。
JSON の構造変更に強く、拡張性が高い。
プロパティを追加するだけで新しい JSON 項目を取り込める。
手動の TryGetProperty が不要。

デメリット

❌ JSON の一部分だけを取得したい場合は、全体のデシリアライズが不要に感じることもある。


3. 実践:天気情報を取得するアプリケーション

3.1. JsonSerializer.Deserialize<T>() を用いた最適な実装

以下の Windows Forms アプリケーションでは、コンボボックスから選択された都市の天気アイコンを取得し、表示します。

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;

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

        public Form1()
        {
            InitializeComponent();

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

            foreach (var data in this.cityNames)
            {
                areaBox.Items.Add(data.Key);
            }

            client = new HttpClient();
        }

        private async void CitySelected(object sender, EventArgs e)
        {
            if (!cityNames.ContainsKey(areaBox.Text)) return;

            string cityCode = cityNames[areaBox.Text];
            string url = $"https://example.com/api/weather?city={cityCode}";

            try
            {
                string result = await client.GetStringAsync(url);

                // JSON をクラスに変換
                WeatherResponse? weatherData = JsonSerializer.Deserialize<WeatherResponse>(result);

                if (weatherData != null && !string.IsNullOrEmpty(weatherData.Url))
                {
                    weatherIcon.ImageLocation = weatherData.Url;
                }
                else
                {
                    MessageBox.Show("天気情報が取得できませんでした。");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("天気情報の取得に失敗しました: " + ex.Message);
            }
        }

        private void ExitMenuClicked(object sender, EventArgs e)
        {
            this.Close();
        }
    }

    // JSON のデータ構造を表すクラス
    public class WeatherResponse
    {
        public string Url { get; set; } = string.Empty;
    }
}

4. まとめ

4.1. JsonDocument vs JsonSerializer.Deserialize<T>()

比較ポイントJsonDocumentJsonSerializer.Deserialize<T>()
コードの可読性冗長 (TryGetProperty の使用)シンプル (クラスにマッピング)
拡張性JSON の変更に弱いクラスのプロパティを追加するだけ
UI の応答性Result の使用で UI フリーズの可能性ありawait で UI フリーズなし
エラーハンドリングTryGetProperty で個別チェックが必要null チェックだけで済む

4.2. JsonSerializer.Deserialize<T>() の優位性

コードがシンプルで可読性が高い
拡張性が高く、JSON の変更に柔軟
エラーハンドリングが簡潔
非同期処理 (await) による UI フリーズ防止


5. 結論

JSON を C# で解析する場合、 System.Text.Json.JsonSerializer.Deserialize<T>() を使用する方が効率的 であり、拡張性・可読性・保守性の面で優れています。特に JSON の構造が変更される可能性がある場合オブジェクト指向設計を重視する場合 は、この方法を推奨します。

C#,JSON

Posted by hidepon