C#でJSONを扱う方法を徹底解説|シリアライズ・デシリアライズ・読み込みまでサンプル付き

はじめに

C#でWeb API連携、設定ファイルの保存、ログ出力、外部サービスとのデータ交換を行うとき、JSONはほぼ必ず登場します。JSONは軽量で読み書きしやすく、C#のオブジェクトとも相性がよいため、実務でも非常によく使われるデータ形式です。

この記事では、C#でJSONを扱う基本として、シリアライズ、デシリアライズ、JSONファイルの読み込み、書き込み、配列やネストしたJSONの扱い方まで、サンプルコード付きで解説します。

C#でJSONを扱う方法には、標準ライブラリのSystem.Text.Jsonを使う方法と、外部ライブラリのNewtonsoft.Jsonを使う方法があります。現在の.NETではSystem.Text.Jsonが標準的な選択肢として用意されており、JSONのシリアライズとデシリアライズ機能を提供しています。Microsoft Learn

1. C#でJSONを扱う前に知っておきたい基礎

1-1. JSONとは?C#でよく使われる理由

JSONは「JavaScript Object Notation」の略で、データをテキスト形式で表現するためのフォーマットです。たとえば、ユーザー情報をJSONで表すと次のようになります。

JSON
{
"id": 1,
"name": "山田太郎",
"email": "taro@example.com"
}

JSONは人間が読んでも理解しやすく、プログラムからも扱いやすいのが特徴です。C#では、Web APIのレスポンス、アプリケーション設定、外部システムとのデータ連携などでよく使われます。

C#のクラスとJSONの構造を対応させることで、JSON文字列をC#のオブジェクトに変換したり、C#のオブジェクトをJSON文字列に変換したりできます。

1-2. シリアライズとデシリアライズの違い

C#でJSONを扱うときに必ず出てくる用語が「シリアライズ」と「デシリアライズ」です。

シリアライズとは、C#のオブジェクトをJSON文字列に変換することです。

C#
User user = new User { Id = 1, Name = "山田太郎" };
string json = JsonSerializer.Serialize(user);

一方、デシリアライズとは、JSON文字列をC#のオブジェクトに変換することです。

C#
string json = "{\"Id\":1,\"Name\":\"山田太郎\"}";
User? user = JsonSerializer.Deserialize<User>(json);

つまり、C#からJSONへ変換するのがシリアライズ、JSONからC#へ変換するのがデシリアライズです。

1-3. C#でJSONを扱う主な場面

C#でJSONを扱う場面は多くあります。代表的なのは、Web APIから受け取ったJSONをC#のクラスに変換するケースです。

たとえば、天気情報、商品情報、ユーザー情報などを外部APIから取得すると、多くの場合レスポンスはJSON形式で返されます。そのJSONをC#のクラスにデシリアライズすれば、通常のオブジェクトとして扱えます。

また、アプリケーションの設定ファイルをJSONで保存することもあります。データベースを使うほどではない簡単な設定値であれば、JSONファイルに保存して読み書きする方法が便利です。

1-4. この記事で扱うサンプルコードの前提環境

この記事では、主に次の環境を前提にサンプルコードを紹介します。

.NET 8以降
C# 12以降
コンソールアプリケーション
System.Text.Json

System.Text.Jsonは、.NET Core 3.1以降のランタイムに含まれているため、最近の.NETプロジェクトであれば基本的に追加インストールなしで利用できます。Microsoft Learn

2. C#でJSONを扱う方法は大きく2つ

2-1. System.Text.Jsonを使う方法

System.Text.Jsonは、Microsoftが提供しているC#標準のJSON操作ライブラリです。JSONのシリアライズ、デシリアライズ、プロパティ名の制御、DOM操作などに対応しています。

基本的な使い方は非常にシンプルです。

C#
using System.Text.Json;

string json = JsonSerializer.Serialize(obj);
User? user = JsonSerializer.Deserialize<User>(json);

追加パッケージを入れずに使えることが多いため、新規開発ではまずSystem.Text.Jsonを検討するのがおすすめです。

2-2. Newtonsoft.Jsonを使う方法

Newtonsoft.Jsonは、長年C#で広く使われてきたJSONライブラリです。Json.NETとも呼ばれます。NuGetではNewtonsoft.Jsonとして提供されており、高機能なJSONフレームワークとして利用されています。NuGet

次のようにJsonConvertを使ってJSONを扱います。

C#
using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(obj);
User? user = JsonConvert.DeserializeObject<User>(json);

古いプロジェクトや、柔軟なJSON操作が必要なプロジェクトでは、今でもNewtonsoft.Jsonが使われることがあります。

2-3. System.Text.JsonとNewtonsoft.Jsonの違い

System.Text.Jsonは標準ライブラリとして使いやすく、パフォーマンス面でも有利なケースが多いです。一方、Newtonsoft.Jsonは歴史が長く、柔軟な変換や動的なJSON操作、既存資産との互換性に強みがあります。

たとえば、単純なクラスのシリアライズやデシリアライズであればSystem.Text.Jsonで十分です。逆に、複雑なカスタム変換、既存コードでJObjectを多用している場合、古い.NET Framework環境との互換性が必要な場合はNewtonsoft.Jsonが選ばれることもあります。

Microsoftのドキュメントでも、Newtonsoft.JsonからSystem.Text.Jsonへ移行するための情報がまとめられており、両者には機能差があることを前提に移行方法が説明されています。Microsoft Learn

2-4. 初心者はどちらを使うべきか

これからC#でJSONを学ぶなら、まずはSystem.Text.Jsonから始めるのがおすすめです。標準機能として利用しやすく、基本的なJSON操作であれば十分対応できます。

ただし、仕事で既存プロジェクトに参加する場合は、すでにNewtonsoft.Jsonが使われていることもあります。その場合は無理に置き換えず、プロジェクトの方針に合わせるのが安全です。

3. System.Text.Jsonの基本的な使い方

3-1. 必要なusingと基本構文

System.Text.Jsonを使うには、次のusingを追加します。

C#
using System.Text.Json;

シリアライズにはJsonSerializer.Serializeを使います。

C#
string json = JsonSerializer.Serialize(オブジェクト);

デシリアライズにはJsonSerializer.Deserialize<T>を使います。

C#
T? obj = JsonSerializer.Deserialize<T>(json);

Deserialize<T>の戻り値はnullになる可能性があるため、実務ではnullチェックを入れるのが安全です。

3-2. JSONに変換するクラスを作成する

まずは、JSONに変換するためのC#クラスを用意します。

C#
public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
}

このクラスは、次のようなJSONと対応します。

JSON
{
"Id": 1,
"Name": "山田太郎",
"Email": "taro@example.com"
}

C#のプロパティ名とJSONのキー名が一致していると、特別な設定をしなくても変換できます。

3-3. オブジェクトをJSON文字列にシリアライズする

次に、C#のオブジェクトをJSON文字列に変換します。

C#
using System.Text.Json;

User user = new User
{
Id = 1,
Name = "山田太郎",
Email = "taro@example.com"
};

string json = JsonSerializer.Serialize(user);

Console.WriteLine(json);

実行すると、次のようなJSON文字列が出力されます。

JSON
{"Id":1,"Name":"山田太郎","Email":"taro@example.com"}

このように、JsonSerializer.Serializeを使うだけでC#のオブジェクトをJSONに変換できます。

3-4. JSON文字列をオブジェクトにデシリアライズする

今度は、JSON文字列をC#のオブジェクトに戻します。

C#
using System.Text.Json;

string json = "{\"Id\":1,\"Name\":\"山田太郎\",\"Email\":\"taro@example.com\"}";

User? user = JsonSerializer.Deserialize<User>(json);

if (user != null)
{
Console.WriteLine(user.Id);
Console.WriteLine(user.Name);
Console.WriteLine(user.Email);
}

Deserialize<User>と指定することで、JSON文字列をUserクラスのインスタンスに変換できます。

3-5. 実行結果を確認する

上記のコードを実行すると、次のように表示されます。

1
山田太郎
taro@example.com

JSON文字列の値が、C#のUserオブジェクトの各プロパティに正しく設定されていることが確認できます。

4. C#でJSONファイルを読み込む方法

4-1. JSONファイルを用意する

C#でJSONファイルを読み込む例として、次のようなuser.jsonを用意します。

JSON
{
"Id": 1,
"Name": "山田太郎",
"Email": "taro@example.com"
}

このファイルをコンソールアプリケーションの実行フォルダに配置します。

4-2. File.ReadAllTextでJSONを読み込む

JSONファイルの内容を文字列として読み込むには、File.ReadAllTextを使います。

C#
string json = File.ReadAllText("user.json");
Console.WriteLine(json);

これで、user.jsonの中身を文字列として取得できます。

日本語を含むJSONファイルの場合は、文字コードを明示して読み込むと安全です。

C#
using System.Text;

string json = File.ReadAllText("user.json", Encoding.UTF8);

4-3. 読み込んだJSONをデシリアライズする

読み込んだJSON文字列をUserクラスに変換します。

C#
using System.Text;
using System.Text.Json;

string json = File.ReadAllText("user.json", Encoding.UTF8);

User? user = JsonSerializer.Deserialize<User>(json);

if (user != null)
{
Console.WriteLine($"{user.Name}さんのメールアドレスは{user.Email}です。");
}

実行結果は次のようになります。

山田太郎さんのメールアドレスはtaro@example.comです。

4-4. ファイルが存在しない場合のエラー対策

JSONファイルを読み込むときは、ファイルが存在しない可能性を考慮する必要があります。

C#
using System.Text;
using System.Text.Json;

string path = "user.json";

if (!File.Exists(path))
{
Console.WriteLine("JSONファイルが見つかりません。");
return;
}

try
{
string json = File.ReadAllText(path, Encoding.UTF8);
User? user = JsonSerializer.Deserialize<User>(json);

if (user == null)
{
Console.WriteLine("JSONをユーザー情報に変換できませんでした。");
return;
}

Console.WriteLine(user.Name);
}
catch (JsonException ex)
{
Console.WriteLine($"JSONの形式が不正です: {ex.Message}");
}
catch (IOException ex)
{
Console.WriteLine($"ファイルの読み込みに失敗しました: {ex.Message}");
}

ファイル操作とJSON変換では、それぞれ異なる例外が発生する可能性があります。実務では、File.Existstry-catchを使ってエラーに備えましょう。

4-5. 日本語を含むJSONファイルを扱うときの注意点

日本語を含むJSONファイルでは、文字コードの不一致によって文字化けが起こることがあります。基本的にはUTF-8で保存し、C#側でもUTF-8として読み込むのがおすすめです。

C#
string json = File.ReadAllText("user.json", Encoding.UTF8);

Visual Studio CodeなどのエディタでJSONファイルを作成する場合も、文字コードがUTF-8になっているか確認しておくと安心です。

5. C#でJSONファイルに書き込む方法

5-1. オブジェクトをJSON文字列に変換する

JSONファイルに書き込むには、まずC#のオブジェクトをJSON文字列に変換します。

C#
using System.Text.Json;

User user = new User
{
Id = 2,
Name = "佐藤花子",
Email = "hanako@example.com"
};

string json = JsonSerializer.Serialize(user);

この時点では、まだファイルには保存されていません。json変数にJSON文字列が入っているだけです。

5-2. File.WriteAllTextでJSONファイルを保存する

JSON文字列をファイルに保存するには、File.WriteAllTextを使います。

C#
using System.Text;
using System.Text.Json;

User user = new User
{
Id = 2,
Name = "佐藤花子",
Email = "hanako@example.com"
};

string json = JsonSerializer.Serialize(user);

File.WriteAllText("user.json", json, Encoding.UTF8);

これで、user.jsonにJSONが保存されます。

5-3. インデント付きの読みやすいJSONを出力する

初期状態のJSONは1行で出力されます。人間が読みやすい形式にしたい場合は、JsonSerializerOptionsWriteIndentedtrueにします。

C#
using System.Text;
using System.Text.Json;

User user = new User
{
Id = 2,
Name = "佐藤花子",
Email = "hanako@example.com"
};

JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true
};

string json = JsonSerializer.Serialize(user, options);

File.WriteAllText("user.json", json, Encoding.UTF8);

出力されるJSONは次のようになります。

JSON
{
"Id": 2,
"Name": "佐藤花子",
"Email": "hanako@example.com"
}

設定ファイルのように人が直接確認する可能性があるJSONでは、インデント付きで保存すると管理しやすくなります。

5-4. 既存ファイルを上書き・追記するときの注意点

File.WriteAllTextは、指定したファイルがすでに存在する場合、その内容を上書きします。既存の内容を残したい場合は注意が必要です。

JSONファイルは通常、1つのJSON構造として保存するため、単純な追記には向いていません。ログのように追記したい場合は、JSON配列として読み込み、リストに追加してからファイル全体を書き戻す方法が一般的です。

C#
List<User> users = new List<User>();

if (File.Exists("users.json"))
{
string existingJson = File.ReadAllText("users.json", Encoding.UTF8);
users = JsonSerializer.Deserialize<List<User>>(existingJson) ?? new List<User>();
}

users.Add(new User
{
Id = 3,
Name = "鈴木一郎",
Email = "ichiro@example.com"
});

string newJson = JsonSerializer.Serialize(users, new JsonSerializerOptions
{
WriteIndented = true
});

File.WriteAllText("users.json", newJson, Encoding.UTF8);

6. 配列・リスト・ネストしたJSONを扱う方法

6-1. JSON配列をListにデシリアライズする

複数のデータを扱う場合、JSON配列をC#のList<T>に変換します。

JSON
[
{
"Id": 1,
"Name": "山田太郎",
"Email": "taro@example.com"
},
{
"Id": 2,
"Name": "佐藤花子",
"Email": "hanako@example.com"
}
]

このJSONをList<User>にデシリアライズするコードは次のとおりです。

C#
using System.Text.Json;

string json = File.ReadAllText("users.json");

List<User>? users = JsonSerializer.Deserialize<List<User>>(json);

if (users != null)
{
foreach (User user in users)
{
Console.WriteLine($"{user.Id}: {user.Name}");
}
}

6-2. ListをJSON配列にシリアライズする

C#のList<User>をJSON配列に変換することもできます。

C#
List<User> users = new List<User>
{
new User { Id = 1, Name = "山田太郎", Email = "taro@example.com" },
new User { Id = 2, Name = "佐藤花子", Email = "hanako@example.com" }
};

string json = JsonSerializer.Serialize(users, new JsonSerializerOptions
{
WriteIndented = true
});

Console.WriteLine(json);

実行結果は次のようになります。

JSON
[
{
"Id": 1,
"Name": "山田太郎",
"Email": "taro@example.com"
},
{
"Id": 2,
"Name": "佐藤花子",
"Email": "hanako@example.com"
}
]

6-3. ネストしたJSONをクラスで表現する

JSONでは、オブジェクトの中にさらにオブジェクトを含めることがあります。これをネストしたJSONと呼びます。

JSON
{
"Id": 1,
"Name": "山田太郎",
"Address": {
"PostalCode": "100-0001",
"City": "東京都千代田区"
}
}

このJSONに対応するC#クラスは次のようになります。

C#
public class UserWithAddress
{
public int Id { get; set; }
public string Name { get; set; } = "";
public Address Address { get; set; } = new Address();
}

public class Address
{
public string PostalCode { get; set; } = "";
public string City { get; set; } = "";
}

デシリアライズは通常のオブジェクトと同じです。

C#
string json = File.ReadAllText("user-address.json");

UserWithAddress? user = JsonSerializer.Deserialize<UserWithAddress>(json);

if (user != null)
{
Console.WriteLine(user.Address.City);
}

JSONの階層構造に合わせてC#のクラスも分けると、コードが読みやすくなります。

6-4. 一部の項目だけ取得したい場合の方法

JSON全体をクラスに変換せず、一部の項目だけ取得したい場合はJsonDocumentを使えます。System.Text.Jsonでは、JSON DOMを使うことでJSONペイロード内の要素へランダムアクセスできます。Microsoft Learn

C#
using System.Text.Json;

string json = """
{
"Id": 1,
"Name": "山田太郎",
"Email": "taro@example.com"
}
""";

using JsonDocument document = JsonDocument.Parse(json);

JsonElement root = document.RootElement;
string name = root.GetProperty("Name").GetString() ?? "";

Console.WriteLine(name);

この方法は、JSONの構造が固定されていない場合や、必要な項目が少ない場合に便利です。

7. JSONのプロパティ名を制御する方法

7-1. C#のプロパティ名とJSONのキー名を対応させる

C#ではプロパティ名にパスカルケースを使うことが多いです。

C#
public string UserName { get; set; } = "";

一方、JSONではキャメルケースがよく使われます。

JSON
{
"userName": "taro"
}

このように、C#のプロパティ名とJSONのキー名が異なる場合は、属性やオプションを使って対応させます。

7-2. JsonPropertyName属性を使う

特定のプロパティだけJSONのキー名を変更したい場合は、JsonPropertyName属性を使います。JsonPropertyNameAttributeは、シリアライズおよびデシリアライズ時にJSON内で使われるプロパティ名を指定するための属性です。Microsoft Learn

C#
using System.Text.Json.Serialization;

public class User
{
public int Id { get; set; }

[JsonPropertyName("user_name")]
public string Name { get; set; } = "";

[JsonPropertyName("mail_address")]
public string Email { get; set; } = "";
}

このクラスをシリアライズすると、次のようなJSONになります。

JSON
{
"Id": 1,
"user_name": "山田太郎",
"mail_address": "taro@example.com"
}

外部APIのJSONキー名がC#の命名規則と異なる場合に便利です。

7-3. キャメルケースに変換する

すべてのプロパティ名をキャメルケースにしたい場合は、JsonSerializerOptionsPropertyNamingPolicyJsonNamingPolicy.CamelCaseを指定します。

C#
using System.Text.Json;

User user = new User
{
Id = 1,
Name = "山田太郎",
Email = "taro@example.com"
};

JsonSerializerOptions options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};

string json = JsonSerializer.Serialize(user, options);

Console.WriteLine(json);

出力例は次のとおりです。

JSON
{
"id": 1,
"name": "山田太郎",
"email": "taro@example.com"
}

Microsoftのドキュメントでも、System.Text.Jsonでプロパティ名や値をカスタマイズする方法として、命名ポリシーや属性による制御が説明されています。Microsoft Learn

7-4. nullの項目を出力しない設定にする

JSONにnullのプロパティを出力したくない場合は、DefaultIgnoreConditionを設定します。

C#
using System.Text.Json;
using System.Text.Json.Serialization;

public class UserProfile
{
public string Name { get; set; } = "";
public string? Nickname { get; set; }
}

UserProfile profile = new UserProfile
{
Name = "山田太郎",
Nickname = null
};

JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

string json = JsonSerializer.Serialize(profile, options);

Console.WriteLine(json);

出力結果は次のようになります。

JSON
{
"Name": "山田太郎"
}

Nicknamenullのため、JSONには出力されません。

8. Newtonsoft.Jsonを使ったJSON操作

8-1. Newtonsoft.Jsonのインストール方法

Newtonsoft.Jsonを使うには、NuGetパッケージをインストールします。

Visual Studioの場合は、NuGetパッケージマネージャーでNewtonsoft.Jsonを検索してインストールします。

.NET CLIを使う場合は、次のコマンドを実行します。

Bash
dotnet add package Newtonsoft.Json

インストール後、コードの先頭に次のusingを追加します。

C#
using Newtonsoft.Json;

8-2. JsonConvert.SerializeObjectでシリアライズする

Newtonsoft.JsonでC#のオブジェクトをJSONに変換するには、JsonConvert.SerializeObjectを使います。

C#
using Newtonsoft.Json;

User user = new User
{
Id = 1,
Name = "山田太郎",
Email = "taro@example.com"
};

string json = JsonConvert.SerializeObject(user);

Console.WriteLine(json);

インデント付きで出力したい場合は、Formatting.Indentedを指定します。

C#
string json = JsonConvert.SerializeObject(user, Formatting.Indented);

8-3. JsonConvert.DeserializeObjectでデシリアライズする

JSON文字列をC#のオブジェクトに変換するには、JsonConvert.DeserializeObject<T>を使います。

C#
using Newtonsoft.Json;

string json = "{\"Id\":1,\"Name\":\"山田太郎\",\"Email\":\"taro@example.com\"}";

User? user = JsonConvert.DeserializeObject<User>(json);

if (user != null)
{
Console.WriteLine(user.Name);
}

System.Text.Jsonと似た感覚で使えるため、基本的なJSON操作であれば難しくありません。

8-4. JObjectを使って動的にJSONを扱う

Newtonsoft.Jsonでは、JObjectを使ってJSONを動的に扱えます。

C#
using Newtonsoft.Json.Linq;

string json = """
{
"id": 1,
"name": "山田太郎",
"address": {
"city": "東京都"
}
}
""";

JObject obj = JObject.Parse(json);

string name = obj["name"]?.ToString() ?? "";
string city = obj["address"]?["city"]?.ToString() ?? "";

Console.WriteLine(name);
Console.WriteLine(city);

クラスを定義せずにJSONの一部を取り出したい場合に便利です。

8-5. Newtonsoft.Jsonが向いているケース

Newtonsoft.Jsonが向いているのは、既存プロジェクトで使われている場合や、JObjectを使った柔軟なJSON操作が必要な場合です。

また、古い.NET FrameworkプロジェクトではNewtonsoft.Jsonが採用されていることも多くあります。新規開発ではSystem.Text.Jsonを基本にしつつ、必要に応じてNewtonsoft.Jsonを選ぶとよいでしょう。

9. C#でJSONを扱うときによくあるエラーと対処法

9-1. JSONの形式が不正な場合

JSONのカンマ忘れ、ダブルクォーテーションの不足、余計な文字などがあると、デシリアライズ時にエラーになります。

不正なJSONの例です。

JSON
{
"Id": 1,
"Name": "山田太郎",
}

最後のプロパティの後に余計なカンマがあります。このようなJSONを読み込むと、JsonExceptionが発生する可能性があります。

C#
try
{
User? user = JsonSerializer.Deserialize<User>(json);
}
catch (JsonException ex)
{
Console.WriteLine($"JSONの形式が不正です: {ex.Message}");
}

JSONを扱うときは、例外処理を入れておくことが重要です。

9-2. クラスのプロパティ名が一致しない場合

JSONのキー名とC#のプロパティ名が一致しないと、値が正しく設定されないことがあります。

JSON
{
"user_name": "山田太郎"
}
C#
public class User
{
public string Name { get; set; } = "";
}

この場合、user_nameNameが対応していないため、Nameに値が入りません。対処するには、JsonPropertyNameを使います。

C#
public class User
{
[JsonPropertyName("user_name")]
public string Name { get; set; } = "";
}

9-3. null参照が発生する場合

デシリアライズに失敗した場合や、JSONに項目が存在しない場合、値がnullになることがあります。

C#
User? user = JsonSerializer.Deserialize<User>(json);

Console.WriteLine(user.Name);

このコードは、usernullの場合に例外が発生します。次のようにnullチェックを入れましょう。

C#
User? user = JsonSerializer.Deserialize<User>(json);

if (user == null)
{
Console.WriteLine("ユーザー情報を読み込めませんでした。");
return;
}

Console.WriteLine(user.Name);

文字列プロパティについても、string?stringの使い分けを意識すると安全です。

9-4. 日付や数値の変換で失敗する場合

JSONでは日付や数値が文字列として渡されることがあります。

JSON
{
"Id": "1",
"CreatedAt": "2026-06-16T10:00:00"
}

C#側でIdintとして定義している場合、JSONの値が文字列だと変換に失敗することがあります。APIの仕様に合わせて、C#側の型を調整するか、カスタム変換を検討しましょう。

日付はDateTimeDateTimeOffsetで受け取れますが、フォーマットが標準的でない場合は変換に失敗する可能性があります。

C#
public class LogItem
{
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
}

外部APIのJSONを扱う場合は、日付形式と数値形式を事前に確認しておくことが大切です。

9-5. 文字コードが原因で文字化けする場合

日本語が文字化けする場合は、ファイルの保存形式とC#側の読み込みエンコーディングが一致していない可能性があります。

C#
string json = File.ReadAllText("settings.json", Encoding.UTF8);

書き込み時もUTF-8を指定しておくと安全です。

C#
File.WriteAllText("settings.json", json, Encoding.UTF8);

特にWindows環境で古いテキストファイルを扱う場合、Shift_JISとUTF-8の違いに注意しましょう。

10. 実践サンプル:設定ファイルをJSONで読み書きする

10-1. 設定用クラスを作成する

実務でよくある例として、アプリケーション設定をJSONファイルで保存するサンプルを作成します。

まず、設定用のクラスを定義します。

C#
public class AppSettings
{
public string AppName { get; set; } = "SampleApp";
public string Theme { get; set; } = "Light";
public int FontSize { get; set; } = 14;
public bool AutoSave { get; set; } = true;
}

このクラスをJSONにすると、アプリの設定ファイルとして利用できます。

10-2. 初期設定をJSONファイルに保存する

初期設定をsettings.jsonとして保存します。

C#
using System.Text;
using System.Text.Json;

AppSettings settings = new AppSettings();

JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true
};

string json = JsonSerializer.Serialize(settings, options);

File.WriteAllText("settings.json", json, Encoding.UTF8);

保存されるJSONは次のようになります。

JSON
{
"AppName": "SampleApp",
"Theme": "Light",
"FontSize": 14,
"AutoSave": true
}

10-3. アプリ起動時にJSONファイルを読み込む

アプリ起動時に設定ファイルを読み込みます。ファイルが存在しない場合は、初期設定を作成するようにします。

C#
using System.Text;
using System.Text.Json;

string path = "settings.json";

AppSettings settings;

if (File.Exists(path))
{
string json = File.ReadAllText(path, Encoding.UTF8);
settings = JsonSerializer.Deserialize<AppSettings>(json) ?? new AppSettings();
}
else
{
settings = new AppSettings();

string json = JsonSerializer.Serialize(settings, new JsonSerializerOptions
{
WriteIndented = true
});

File.WriteAllText(path, json, Encoding.UTF8);
}

Console.WriteLine($"アプリ名: {settings.AppName}");
Console.WriteLine($"テーマ: {settings.Theme}");
Console.WriteLine($"フォントサイズ: {settings.FontSize}");
Console.WriteLine($"自動保存: {settings.AutoSave}");

このようにすると、初回起動時には設定ファイルを作成し、2回目以降は既存の設定を読み込めます。

10-4. 設定を変更して再保存する

読み込んだ設定を変更して、再度JSONファイルに保存します。

C#
settings.Theme = "Dark";
settings.FontSize = 16;
settings.AutoSave = false;

string updatedJson = JsonSerializer.Serialize(settings, new JsonSerializerOptions
{
WriteIndented = true
});

File.WriteAllText(path, updatedJson, Encoding.UTF8);

これで、変更後の設定がsettings.jsonに保存されます。

10-5. 実務で使うときの改善ポイント

実務で設定ファイルをJSONで扱う場合は、次の点を意識すると安全です。

設定ファイルが壊れている場合に備えて、try-catchを入れることが重要です。また、設定項目を追加したときに古いJSONファイルでも動作するよう、プロパティには初期値を設定しておくと安心です。

さらに、パスワードやAPIキーなどの機密情報をJSONファイルにそのまま保存するのは避けましょう。どうしても保存が必要な場合は、暗号化やOSの安全な資格情報ストアの利用を検討してください。

11. C#でJSONを扱うときのベストプラクティス

11-1. 基本はSystem.Text.Jsonを使う

新規のC#プロジェクトでは、まずSystem.Text.Jsonを使うのがおすすめです。標準機能として利用でき、基本的なシリアライズ、デシリアライズ、プロパティ名の制御、JSON DOM操作に対応しています。

既存プロジェクトでNewtonsoft.Jsonが使われている場合は、無理に混在させず、プロジェクト全体の方針に合わせることが大切です。

11-2. JSON構造に合わせたクラスを定義する

JSONを扱うときは、できるだけJSON構造に合わせたC#クラスを定義しましょう。

C#
public class ApiResponse
{
public string Status { get; set; } = "";
public List<User> Users { get; set; } = new();
}

クラスを定義しておくと、補完が効きやすく、型安全にデータを扱えます。JsonDocumentJObjectによる動的な操作は便利ですが、使いすぎるとタイプミスに気づきにくくなります。

11-3. 例外処理を必ず入れる

JSONファイルやAPIレスポンスは、常に正しいとは限りません。ファイルが存在しない、JSON形式が壊れている、想定外の値が入っている、といったケースに備える必要があります。

C#
try
{
string json = File.ReadAllText("settings.json", Encoding.UTF8);
AppSettings? settings = JsonSerializer.Deserialize<AppSettings>(json);
}
catch (FileNotFoundException)
{
Console.WriteLine("設定ファイルが見つかりません。");
}
catch (JsonException)
{
Console.WriteLine("設定ファイルのJSON形式が不正です。");
}
catch (IOException)
{
Console.WriteLine("設定ファイルの読み込みに失敗しました。");
}

エラーが起きたときにアプリ全体が停止しないよう、適切に例外処理を入れましょう。

11-4. 大きなJSONファイルではメモリ使用量に注意する

File.ReadAllTextはファイル全体を一度にメモリへ読み込みます。そのため、大きなJSONファイルを扱う場合はメモリ使用量に注意が必要です。

小さな設定ファイルや通常のAPIレスポンスであれば問題になりにくいですが、数百MB以上のJSONを扱う場合は、ストリーム処理や逐次読み込みを検討しましょう。

11-5. APIレスポンスのJSONは仕様変更に備える

外部APIのJSONは、将来的に項目が追加されたり、値がnullになったりする可能性があります。そのため、C#側のクラスはある程度変更に強くしておくことが大切です。

たとえば、必須でない項目はnullableにします。

C#
public class ApiUser
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string? Nickname { get; set; }
}

また、APIレスポンスを扱う箇所では、nullチェックや例外処理を丁寧に行いましょう。

12. C#のJSON操作に関するよくある質問

12-1. C#でJSONを整形して出力するには?

System.Text.Jsonでは、JsonSerializerOptionsWriteIndentedtrueにします。

C#
string json = JsonSerializer.Serialize(obj, new JsonSerializerOptions
{
WriteIndented = true
});

これにより、改行とインデント付きの読みやすいJSONを出力できます。

12-2. JSONの一部だけ読み込むには?

JSON全体をクラスに変換せず、一部だけ取得したい場合はJsonDocumentを使います。

C#
using JsonDocument document = JsonDocument.Parse(json);

string name = document.RootElement
.GetProperty("Name")
.GetString() ?? "";

変更可能なJSON DOMが必要な場合は、JsonNodeJsonObjectJsonArrayなども選択肢になります。Microsoftのドキュメントでは、JsonNodeは変更可能なDOM、JsonDocumentは変更不可のDOMとして説明されています。Microsoft Learn

12-3. DictionaryでJSONを扱うには?

キーと値の組み合わせでJSONを扱いたい場合は、Dictionary<string, string>Dictionary<string, object>を使えます。

C#
Dictionary<string, string> data = new Dictionary<string, string>
{
["name"] = "山田太郎",
["email"] = "taro@example.com"
};

string json = JsonSerializer.Serialize(data, new JsonSerializerOptions
{
WriteIndented = true
});

Console.WriteLine(json);

出力例です。

JSON
{
"name": "山田太郎",
"email": "taro@example.com"
}

JSONの構造が固定されている場合はクラス、動的なキーを扱う場合はDictionaryを使うとよいでしょう。

12-4. privateプロパティはJSONに変換できる?

基本的には、publicなプロパティを使うのが一般的です。JSONとして入出力したい値は、次のようにpublicプロパティとして定義しましょう。

C#
public class User
{
public string Name { get; set; } = "";
}

privateな値までJSONに含めたい場合は設計を見直し、外部に保存してよい情報かどうかを確認することが重要です。機密情報や内部状態を不用意にJSONへ出力すると、セキュリティや保守性の問題につながります。

12-5. System.Text.Jsonでできないことはある?

System.Text.Jsonは多くのJSON操作に対応していますが、既存プロジェクトでNewtonsoft.Json特有の機能を使っている場合は、移行時に差分を確認する必要があります。MicrosoftもNewtonsoft.JsonからSystem.Text.Jsonへの移行ガイドを公開しており、機能差を踏まえた移行方法が説明されています。Microsoft Learn

通常のシリアライズ、デシリアライズ、ファイル読み書き、プロパティ名の制御であれば、まずはSystem.Text.Jsonで十分です。複雑な変換や既存コードとの互換性が必要な場合に、Newtonsoft.Jsonを検討するとよいでしょう。

まとめ

C#でJSONを扱う基本は、オブジェクトをJSONに変換するシリアライズと、JSONをオブジェクトに変換するデシリアライズです。System.Text.Jsonを使えば、標準機能だけで多くのJSON操作に対応できます。

JSONファイルを読み込む場合はFile.ReadAllText、保存する場合はFile.WriteAllTextを使い、文字コードにはUTF-8を指定すると安心です。配列はList<T>、ネストしたJSONは階層に合わせたクラス、一部だけ取得したい場合はJsonDocumentを使うと効率よく扱えます。

新規開発では基本的にSystem.Text.Jsonを使い、既存プロジェクトや柔軟な動的操作が必要な場合はNewtonsoft.Jsonを検討しましょう。JSONの形式不正、null参照、文字化け、型変換エラーなどに備えて例外処理を入れておくことで、実務でも安全にC#のJSON操作を実装できます。