概要

JSON (JavaScript Object Notation) は、データを格納・交換するための軽量なテキストベースのフォーマットである。

C#では、JSONデータの操作が便利に行えるようになっている。

主に、System.Text.Json名前空間を使用してJSONの処理を行う。
この名前空間には、JSONのシリアライズ (オブジェクトをJSON文字列に変換) とデシリアライズ (JSON文字列をオブジェクトに変換) を行うためのクラスやメソッドが含まれている。

JSONファイルの読み込みは、通常のテキストファイルと同様にFile.ReadAllTextメソッドを使用して行う。
その後、JsonSerializer.Deserialize<T>メソッドを使用して、JSONデータをC#のオブジェクトに変換する。

逆に、C#のオブジェクトをJSONファイルとして保存する場合は、まず、JsonSerializer.Serializeメソッドを使用してオブジェクトをJSON文字列に変換して、
その後、File.WriteAllTextメソッドでファイルに書き込む。

JSONデータの操作には、動的な方法と静的な方法がある。

  • 動的な方法
    JsonDocument.Parseメソッドを使用してJSONデータを解析して、JsonElement型を通じてデータにアクセスする。
  • 静的な方法
    JSONデータ構造に対応するC#のクラスを定義して、そのクラスのインスタンスとしてデータを扱う。


C#では、LINQ to JSONを使用することにより、JSONデータに対して複雑なクエリやフィルタリングを行うことも可能である。
これにより、大規模なJSONデータセットから必要な情報を効率的に抽出することができる。

※注意
大規模なJSONファイルを1度にメモリに読み込むとパフォーマンスの問題が生じる可能性がある。
このような場合は、JsonDocument.ParseAsyncメソッドを使用してストリーミング処理を行うことにより、メモリ使用量を抑えることができる。

また、セキュリティの観点から、信頼できないソースからのJSONデータを扱う場合は、適切なバリデーションを行うことが重要である。
不正なデータによる脆弱性を防ぐため、デシリアライズ時には型チェックや範囲チェックを実施することを推奨する。


動的な方法

JSONファイルの読み込み

以下の例では、非同期処理およびストリーミング処理を使用して、JSONファイルの読み込んでいる。

具体的には、JsonDocument.ParseAsyncメソッドを使用してJSONデータを非同期で解析して、JsonElementクラスを通じてデータにアクセスしている。
また、FileStreamクラスを使用してストリーミング処理することにより、大きなJSONファイルを扱う場合にもメモリ効率が向上している。

 using System;
 using System.IO;
 using System.Text.Json;
 using System.Threading.Tasks;
 
 class JsonFileReader
 {
    public static async Task ReadJsonFileAsync(string filePath)
    {
       try
       {
          using FileStream fileStream = File.OpenRead(filePath);
          using JsonDocument document = await JsonDocument.ParseAsync(fileStream);
 
          JsonElement root = document.RootElement;
 
          // JSONの構造に応じて、適切にデータにアクセス
          if (root.TryGetProperty("name", out JsonElement nameElement))
          {
             Console.WriteLine($"名前: {nameElement.GetString()}");
          }
 
          if (root.TryGetProperty("age", out JsonElement ageElement))
          {
             Console.WriteLine($"年齢: {ageElement.GetInt32()}");
          }
 
          if (root.TryGetProperty("hobbies", out JsonElement hobbiesElement) && hobbiesElement.ValueKind == JsonValueKind.Array)
          {
             Console.WriteLine("趣味:");
             foreach (JsonElement hobby in hobbiesElement.EnumerateArray())
             {
                Console.WriteLine($"- {hobby.GetString()}");
             }
          }
       }
       catch (FileNotFoundException)
       {
          Console.WriteLine("エラー: 指定されたファイルが存在しない");
       }
       catch (JsonException ex)
       {
          Console.WriteLine($"JSONパースエラー: {ex.Message}");
       }
       catch (Exception ex)
       {
          Console.WriteLine($"予期せぬエラーが発生: {ex.Message}");
       }
    }
 }


以下の例では、上記のクラスを使用してJSONファイルを読み込んでいる。

 class Program
 {
    static async Task Main(string[] args)
    {
       string readFilePath = "sample.json";
 
       // JSONファイルの読み込み
       await JsonFileReader.ReadJsonFileAsync(readFilePath);
    }
 }


JSONファイルの書き込み

以下の例では、非同期処理およびストリーミング処理を使用して、JSONファイルの書き込んでいる。

具体的には、JsonSerializer.SerializeAsyncメソッドを使用してオブジェクトをJSONに非同期でシリアライズして、ファイルに書き込んでいる。
また、FileStreamクラスを使用してストリーミング処理することにより、大きなJSONファイルを扱う場合にもメモリ効率が向上している。

 using System;
 using System.IO;
 using System.Text.Json;
 using System.Threading.Tasks;
 
 class JsonFileWriter
 {
    public static async Task WriteJsonFileAsync(string filePath, object data)
    {
       try
       {
          using FileStream createStream = File.Create(filePath);
          await JsonSerializer.SerializeAsync(createStream, data, new JsonSerializerOptions
          {
             WriteIndented = true  // 整形されたJSONを出力
          });
 
          Console.WriteLine("JSONファイルの書き込みが完了");
       }
       catch (UnauthorizedAccessException)
       {
          Console.WriteLine("エラー: ファイルへの書き込み権限がない");
       }
       catch (JsonException ex)
       {
          Console.WriteLine($"JSONシリアライズエラー: {ex.Message}");
       }
       catch (Exception ex)
       {
          Console.WriteLine($"予期せぬエラーが発生: {ex.Message}");
       }
    }
 }


以下の例では、上記のクラスを使用してJSONファイルを書き込んでいる。

 class Program
 {
    static async Task Main(string[] args)
    {
       string writeFilePath = "sample.json";
 
       // JSONファイルの書き込み
       var data = new
       {
          name = "山田太郎",
          age = 30,
          hobbies = new[] { "読書", "旅行", "料理" }
       };
 
       await JsonFileWriter.WriteJsonFileAsync(writeFilePath, data);
    }
 }