C#でJSONを扱う方法|読み込み・変換・シリアライズを初心者向けに解説

はじめに

C#でアプリケーションを開発していると、JSONを扱う場面は非常に多くあります。たとえば、Web APIから取得したデータを読み込む、設定ファイルをJSONで管理する、C#のオブジェクトをJSON形式で保存する、外部サービスへJSONデータを送信する、といったケースです。

JSONは軽量で読み書きしやすく、Web開発やアプリ開発で広く使われているデータ形式です。C#では、標準ライブラリであるSystem.Text.Jsonを使う方法と、長年利用されてきたNewtonsoft.Jsonを使う方法が代表的です。

この記事では、C#でJSONを扱う方法について、読み込み、変換、シリアライズ、デシリアライズ、ファイル保存、エラー対策まで初心者向けに解説します。

1. C#でJSONを扱う基本

1-1. JSONとは何か

JSONとは、「JavaScript Object Notation」の略で、データをテキスト形式で表現するためのフォーマットです。名前にJavaScriptとありますが、C#、Java、Python、PHPなど多くの言語で利用されています。

JSONは、次のようにキーと値の組み合わせでデータを表します。

JSON
{
"name": "Taro",
"age": 30,
"isActive": true
}

この例では、nameageisActiveがキーで、それぞれに文字列、数値、真偽値が設定されています。JSONは人間にも読みやすく、プログラムでも解析しやすいため、Web APIや設定ファイルでよく使われます。

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

C#でJSONを扱う主な場面には、次のようなものがあります。

Web APIから返ってきたJSONレスポンスをC#のクラスに変換する場合、C#のオブジェクトをJSON文字列に変換してAPIへ送信する場合、アプリケーションの設定情報をJSONファイルとして保存する場合、一覧データをJSON配列として管理する場合などです。

たとえば、ユーザー情報をWeb APIから取得すると、次のようなJSONが返ってくることがあります。

JSON
{
"id": 1,
"name": "Yamada",
"email": "yamada@example.com"
}

C#では、このJSONを文字列として読み込むだけでなく、Userクラスのオブジェクトに変換して扱うことができます。

1-3. JSON処理でよく使う用語

C#でJSONを扱う前に、よく使う用語を押さえておきましょう。

シリアライズとは、C#のオブジェクトをJSON文字列に変換することです。たとえば、Userオブジェクトを{"name":"Taro","age":30}のようなJSONに変換します。

デシリアライズとは、JSON文字列をC#のオブジェクトに変換することです。Web APIから取得したJSONをUserクラスに変換するような処理が該当します。

パースとは、JSON文字列を解析して、プログラムから扱える形にすることです。クラスに変換せず、JSONの中身を直接読み取る場合にも使われます。

1-4. C#でJSONを扱う代表的なライブラリ

C#でJSONを扱う代表的なライブラリは、System.Text.JsonNewtonsoft.Jsonです。

System.Text.Jsonは、.NETに標準で用意されているJSON処理用の名前空間で、JSONのシリアライズとデシリアライズに対応しています。Microsoftの公式ドキュメントでも、.NETにおけるJSONのシリアライズとデシリアライズ機能として説明されています。Microsoft Learn

一方、Newtonsoft.Jsonは「Json.NET」とも呼ばれ、長く使われてきた定番ライブラリです。JsonConvertを使って、JSON文字列と.NETオブジェクトを簡単に変換できます。Newtonsoft

2. C#でJSONを扱う方法の選び方

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

現在のC#開発では、まずSystem.Text.Jsonの利用を検討するのがおすすめです。標準ライブラリとして使えるため、追加のNuGetパッケージを入れずにJSON処理を始められます。

基本的な使い方は、JsonSerializer.SerializeでオブジェクトをJSONに変換し、JsonSerializer.DeserializeでJSONをオブジェクトに変換します。

C#
using System.Text.Json;

var user = new User
{
Name = "Taro",
Age = 30
};

string json = JsonSerializer.Serialize(user);
Console.WriteLine(json);

クラスは次のように定義します。

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

System.Text.Jsonは、標準的なJSON処理であれば十分に対応できます。新しくC#でJSON処理を始める場合は、まずこの方法を覚えるとよいでしょう。

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

Newtonsoft.Jsonを使う場合は、NuGetからNewtonsoft.Jsonパッケージをインストールします。インストール後、JsonConvert.SerializeObjectJsonConvert.DeserializeObjectを使ってJSONを扱います。

C#
using Newtonsoft.Json;

var user = new User
{
Name = "Taro",
Age = 30
};

string json = JsonConvert.SerializeObject(user);
Console.WriteLine(json);

JSONからオブジェクトへ変換する場合は、次のように書きます。

C#
string json = "{\"Name\":\"Taro\",\"Age\":30}";

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

Console.WriteLine(user?.Name);

Newtonsoft.Jsonは機能が豊富で、古いプロジェクトや既存システムでもよく利用されています。複雑なJSON変換や柔軟なカスタマイズが必要な場合に選ばれることがあります。

2-3. どちらのライブラリを選ぶべきか

新規開発で基本的なJSON処理を行うなら、System.Text.Jsonを選ぶのが自然です。標準機能として利用でき、追加ライブラリなしで始められるためです。

一方、既存プロジェクトでNewtonsoft.Jsonが使われている場合や、System.Text.Jsonでは対応しにくい変換処理が必要な場合は、Newtonsoft.Jsonを使い続ける選択もあります。

大切なのは、プロジェクト内でJSONライブラリを混在させすぎないことです。場所によってSystem.Text.JsonNewtonsoft.Jsonが混在すると、日付形式、プロパティ名、nullの扱いなどで挙動が変わり、保守しにくくなる場合があります。

2-4. 初心者におすすめの使い分け

初心者の場合は、まずSystem.Text.Jsonから学ぶのがおすすめです。C#の標準的な書き方に近く、基本的なシリアライズ、デシリアライズ、ファイル読み込み、APIレスポンス処理を十分に行えます。

次のように考えると選びやすくなります。

新規プロジェクトではSystem.Text.Json、既存プロジェクトで使われている場合はNewtonsoft.Json、複雑なJSON操作や古いコードとの互換性が必要な場合もNewtonsoft.Json、という使い分けです。

3. C#でJSONを読み込む方法

3-1. JSON文字列を読み込む方法

C#でJSON文字列を読み込むには、JsonSerializer.Deserializeを使います。

C#
using System.Text.Json;

string json = "{\"Name\":\"Taro\",\"Age\":30}";

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

Console.WriteLine(user?.Name);
Console.WriteLine(user?.Age);

このコードでは、JSON文字列をUserクラスのオブジェクトに変換しています。Deserialize<User>のように型を指定することで、C#のオブジェクトとして扱えるようになります。

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

JSONのキー名とC#のプロパティ名が一致していると、値が自動的にマッピングされます。

3-2. JSONファイルを読み込む方法

JSONファイルを読み込む場合は、File.ReadAllTextでファイルの内容を文字列として読み込み、その文字列をデシリアライズします。

C#
using System.Text.Json;

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

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

Console.WriteLine(user?.Name);

user.jsonの内容は次のようになります。

JSON
{
"Name": "Taro",
"Age": 30
}

ファイル読み込みでは、ファイルが存在しない場合やJSONの形式が間違っている場合に例外が発生することがあります。そのため、実際のアプリケーションではtry-catchを使って安全に読み込むことが重要です。

3-3. Web APIのレスポンスJSONを読み込む方法

Web APIからJSONを取得する場合は、HttpClientを使います。

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

using var client = new HttpClient();

string json = await client.GetStringAsync("https://example.com/api/users/1");

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

Console.WriteLine(user?.Name);

APIのレスポンスは文字列として取得されるため、その後にJsonSerializer.DeserializeでC#のクラスに変換します。

実際の開発では、HTTPステータスコードの確認、通信エラーへの対応、タイムアウト設定なども必要です。まずは「APIからJSON文字列を取得し、C#のクラスに変換する」という流れを理解しましょう。

3-4. 読み込んだJSONの値を取得する方法

クラスに変換せずにJSONの値を取得したい場合は、JsonDocumentを使えます。JsonDocumentはJSONをDOMとして解析し、RootElementから各値にアクセスできます。Microsoftのドキュメントでは、JsonDocumentにより読み取り専用DOMを構築し、JsonElementでJSON要素へアクセスできると説明されています。Microsoft Learn

C#
using System.Text.Json;

string json = "{\"name\":\"Taro\",\"age\":30}";

using JsonDocument document = JsonDocument.Parse(json);

JsonElement root = document.RootElement;

string name = root.GetProperty("name").GetString() ?? "";
int age = root.GetProperty("age").GetInt32();

Console.WriteLine(name);
Console.WriteLine(age);

GetPropertyでキーを指定し、GetStringGetInt32で値を取得します。JSONの構造が固定されていない場合や、一部の値だけ取得したい場合に便利です。

4. C#でJSONをクラスに変換する方法

4-1. JSONに対応するC#クラスを作成する

JSONをC#のオブジェクトに変換するには、JSONの構造に対応したクラスを作成します。

たとえば、次のJSONがあるとします。

JSON
{
"id": 1,
"name": "Taro",
"email": "taro@example.com"
}

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

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

JSONのキーに対応するプロパティを用意することで、デシリアライズ時に値が自動的に設定されます。

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

JSONをオブジェクトに変換する処理をデシリアライズと呼びます。

C#
using System.Text.Json;

string json = """
{
"Id": 1,
"Name": "Taro",
"Email": "taro@example.com"
}
""";

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

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

Deserialize<User>のように変換先の型を指定することで、JSONをUserオブジェクトとして扱えます。

Deserializeの戻り値はnullになる可能性があるため、実際のコードではnullチェックを入れると安全です。

4-3. 配列形式のJSONをListに変換する

JSONでは、複数のデータを配列として表すことがあります。

JSON
[
{
"Id": 1,
"Name": "Taro"
},
{
"Id": 2,
"Name": "Hanako"
}
]

このようなJSON配列は、C#ではList<T>に変換できます。

C#
using System.Text.Json;

string json = """
[
{
"Id": 1,
"Name": "Taro"
},
{
"Id": 2,
"Name": "Hanako"
}
]
""";

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

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

複数件のデータを扱うWeb APIでは、JSON配列が返されることがよくあります。その場合は、List<User>User[]に変換して処理します。

4-4. ネストしたJSONをクラスに変換する

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

JSON
{
"Id": 1,
"Name": "Taro",
"Address": {
"Prefecture": "Tokyo",
"City": "Shibuya"
}
}

この場合、C#側でもネストに対応したクラスを作成します。

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

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

デシリアライズは通常のJSONと同じです。

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

Console.WriteLine(user?.Address.City);

ネストが深いJSONほど、クラス設計が重要になります。JSONの構造に合わせて、責務ごとにクラスを分けると保守しやすくなります。

4-5. プロパティ名が異なる場合の対応方法

JSONのキー名とC#のプロパティ名が異なる場合は、JsonPropertyName属性を使います。

JSON
{
"user_name": "Taro",
"user_age": 30
}

C#側では次のように書きます。

C#
using System.Text.Json.Serialization;

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

[JsonPropertyName("user_age")]
public int Age { get; set; }
}

これにより、JSONのuser_nameがC#のNameプロパティに、user_ageAgeプロパティに対応します。

また、大文字と小文字の違いだけを吸収したい場合は、JsonSerializerOptionsPropertyNameCaseInsensitiveを使えます。このオプションは、デシリアライズ時にプロパティ名の大文字小文字を区別しない比較を行うかどうかを設定するもので、既定値はfalseです。Microsoft Learn

C#
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};

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

5. C#のオブジェクトをJSONに変換する方法

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

C#のオブジェクトをJSON文字列に変換するには、JsonSerializer.Serializeを使います。

C#
using System.Text.Json;

var user = new User
{
Id = 1,
Name = "Taro",
Email = "taro@example.com"
};

string json = JsonSerializer.Serialize(user);

Console.WriteLine(json);

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

JSON
{"Id":1,"Name":"Taro","Email":"taro@example.com"}

このように、C#のオブジェクトを簡単にJSON形式へ変換できます。APIへデータを送信する場合や、ファイルに保存する場合によく使います。

5-2. Listや配列をJSONに変換する

List<T>や配列もJSONに変換できます。

C#
using System.Text.Json;

var users = new List<User>
{
new User { Id = 1, Name = "Taro", Email = "taro@example.com" },
new User { Id = 2, Name = "Hanako", Email = "hanako@example.com" }
};

string json = JsonSerializer.Serialize(users);

Console.WriteLine(json);

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

JSON
[{"Id":1,"Name":"Taro","Email":"taro@example.com"},{"Id":2,"Name":"Hanako","Email":"hanako@example.com"}]

一覧データを保存したい場合や、複数件のデータをAPIに送信したい場合に便利です。

5-3. JSONを見やすく整形して出力する

そのままシリアライズすると、JSONは1行で出力されます。人間が読みやすい形式で出力したい場合は、WriteIndentedtrueにします。WriteIndentedはJSONを整形して出力するための設定で、既定では余分な空白を入れずにシリアライズされます。Microsoft Learn

C#
var options = new JsonSerializerOptions
{
WriteIndented = true
};

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

Console.WriteLine(json);

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

JSON
{
"Id": 1,
"Name": "Taro",
"Email": "taro@example.com"
}

設定ファイルやログ出力など、人間がJSONを直接読む可能性がある場合は、整形して出力すると扱いやすくなります。

5-4. JSONファイルとして保存する方法

C#のオブジェクトをJSONファイルとして保存するには、シリアライズした文字列をFile.WriteAllTextで書き込みます。

C#
using System.Text.Json;

var user = new User
{
Id = 1,
Name = "Taro",
Email = "taro@example.com"
};

var options = new JsonSerializerOptions
{
WriteIndented = true
};

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

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

日本語を含むJSONを保存する場合は、文字コードにも注意しましょう。通常はUTF-8で保存すれば問題ありません。

C#
File.WriteAllText("user.json", json, System.Text.Encoding.UTF8);

ファイルへ保存する処理では、書き込み権限がない、保存先フォルダが存在しない、ファイルが使用中である、といったエラーが起きることがあります。実用コードでは例外処理を入れるようにしましょう。

6. C#でJSONを動的に扱う方法

6-1. JsonDocumentでJSONを解析する

JSONの構造が固定されていない場合や、一部の値だけ取得したい場合は、クラスを作らずにJsonDocumentで解析できます。

C#
using System.Text.Json;

string json = """
{
"name": "Taro",
"age": 30,
"skills": ["C#", "SQL", "Azure"]
}
""";

using JsonDocument document = JsonDocument.Parse(json);

JsonElement root = document.RootElement;

string name = root.GetProperty("name").GetString() ?? "";

Console.WriteLine(name);

JsonDocument.Parseは、文字列やストリームなどからJSONを解析するために使えます。公式APIドキュメントでも、ParseメソッドはJSON文字列やUTF-8エンコードされたデータを解析するメソッドとして説明されています。Microsoft Learn

6-2. JsonElementで値を取得する

JsonDocumentで解析したJSONの各要素は、JsonElementとして扱います。JsonElementには、文字列、数値、真偽値、配列、オブジェクトなどを取得するためのメソッドが用意されています。配列を列挙するEnumerateArrayなどのAPIも提供されています。Microsoft Learn

C#
JsonElement skills = root.GetProperty("skills");

foreach (JsonElement skill in skills.EnumerateArray())
{
Console.WriteLine(skill.GetString());
}

プロパティが存在しない可能性がある場合は、GetPropertyではなくTryGetPropertyを使うと安全です。

C#
if (root.TryGetProperty("email", out JsonElement emailElement))
{
string email = emailElement.GetString() ?? "";
Console.WriteLine(email);
}
else
{
Console.WriteLine("emailは存在しません。");
}

GetPropertyは指定したキーが存在しない場合に例外が発生するため、外部から受け取るJSONではTryGetPropertyを使うと安心です。

6-3. dynamicを使ってJSONを扱う方法

Newtonsoft.Jsonでは、dynamicを使ってJSONを柔軟に扱うこともできます。

C#
using Newtonsoft.Json;

string json = """
{
"name": "Taro",
"age": 30
}
""";

dynamic? data = JsonConvert.DeserializeObject(json);

Console.WriteLine(data?.name);
Console.WriteLine(data?.age);

dynamicを使うと、クラスを定義せずにJSONの値へアクセスできます。ただし、コンパイル時にプロパティ名の間違いを検出できないため、実行時エラーにつながりやすくなります。

6-4. クラスを作らずにJSONを扱う場合の注意点

クラスを作らずにJSONを扱う方法は便利ですが、使いすぎると保守性が下がります。

たとえば、root.GetProperty("name")のように文字列でキーを指定すると、キー名を間違えてもコンパイル時には分かりません。また、JSONの構造が変わったときに、どの処理が影響を受けるか追いにくくなります。

一時的に値を確認する場合や、構造が固定されていないJSONを扱う場合はJsonDocumentdynamicが便利です。しかし、アプリケーションの中心となるデータは、できるだけC#のクラスを定義して型安全に扱うことをおすすめします。

7. C#のJSON処理でよくあるエラーと対処法

7-1. JSONの形式が正しくない場合

JSONの形式が正しくないと、デシリアライズ時に例外が発生します。

たとえば、次のJSONは末尾のカンマが原因で不正な形式です。

JSON
{
"Name": "Taro",
"Age": 30,
}

正しくは次のように書きます。

JSON
{
"Name": "Taro",
"Age": 30
}

外部ファイルやAPIレスポンスを扱う場合は、常に正しいJSONが来るとは限りません。try-catchで例外処理を入れておくと安全です。

C#
try
{
User? user = JsonSerializer.Deserialize<User>(json);
}
catch (JsonException ex)
{
Console.WriteLine($"JSONの形式が正しくありません: {ex.Message}");
}

7-2. プロパティ名が一致しない場合

JSONのキー名とC#のプロパティ名が一致しないと、期待した値が入らないことがあります。

JSON
{
"user_name": "Taro"
}

C#のプロパティがNameの場合、そのままでは対応できないことがあります。この場合は、JsonPropertyNameを使います。

C#
using System.Text.Json.Serialization;

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

また、大文字小文字の違いだけであれば、PropertyNameCaseInsensitive = trueを指定します。

C#
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};

7-3. nullや空文字でエラーになる場合

JSONには、nullが含まれることがあります。

JSON
{
"Name": null,
"Age": 30
}

C#側でnullを許容していない設計にしていると、後続処理でエラーになる場合があります。

C#
public class User
{
public string? Name { get; set; }
public int Age { get; set; }
}

nullの可能性があるプロパティは、string?のようにnullableとして定義すると意図が明確になります。

値を使うときは、null合体演算子を使うと安全です。

C#
string name = user?.Name ?? "未設定";

空文字とnullは別物です。未入力を空文字で表すのか、値が存在しないことをnullで表すのか、設計段階で決めておくとトラブルを防げます。

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

JSONの日付や数値の形式がC#の型と合わない場合、変換に失敗することがあります。

JSON
{
"CreatedAt": "2026-06-16T10:00:00",
"Price": 1200
}

C#では次のように定義できます。

C#
public class Product
{
public DateTime CreatedAt { get; set; }
public int Price { get; set; }
}

ただし、日付の形式が独自形式だったり、数値が文字列として渡されたりする場合は注意が必要です。

JSON
{
"Price": "1200"
}

このようなJSONでは、変換先の型やオプションを見直す必要があります。外部APIでは、日付や数値の形式が仕様で決まっていることが多いため、API仕様書を確認してC#側の型を合わせましょう。

7-5. 日本語が文字化けする場合

JSONで日本語を扱う場合は、文字コードに注意します。基本的にはUTF-8で読み書きするのがおすすめです。

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

保存時もUTF-8を指定できます。

C#
File.WriteAllText("user.json", json, System.Text.Encoding.UTF8);

また、コンソールに表示した日本語が文字化けする場合は、コンソールのエンコーディング設定が原因のこともあります。

C#
Console.OutputEncoding = System.Text.Encoding.UTF8;

JSONファイル自体、読み込み処理、出力先の環境のどこで文字化けが起きているのかを切り分けることが大切です。

8. C#でJSONを扱う実践サンプル

8-1. 設定ファイルのJSONを読み込むサンプル

アプリケーションの設定情報をJSONファイルで管理する例を見てみましょう。

appsettings.jsonを用意します。

JSON
{
"AppName": "SampleApp",
"Version": "1.0.0",
"MaxUsers": 100
}

対応するクラスを作成します。

C#
public class AppSettings
{
public string AppName { get; set; } = "";
public string Version { get; set; } = "";
public int MaxUsers { get; set; }
}

JSONファイルを読み込みます。

C#
using System.Text.Json;

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

AppSettings? settings = JsonSerializer.Deserialize<AppSettings>(json);

if (settings != null)
{
Console.WriteLine(settings.AppName);
Console.WriteLine(settings.Version);
Console.WriteLine(settings.MaxUsers);
}

設定ファイルをJSONで管理すると、アプリケーションの動作をコード変更なしで調整しやすくなります。

8-2. Web APIからJSONを取得するサンプル

Web APIからJSONを取得してC#のクラスに変換するサンプルです。

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

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

using var client = new HttpClient();

try
{
string json = await client.GetStringAsync("https://example.com/api/users/1");

User? user = JsonSerializer.Deserialize<User>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});

if (user != null)
{
Console.WriteLine(user.Name);
Console.WriteLine(user.Email);
}
}
catch (HttpRequestException ex)
{
Console.WriteLine($"通信エラー: {ex.Message}");
}
catch (JsonException ex)
{
Console.WriteLine($"JSON解析エラー: {ex.Message}");
}

API通信では、通信エラーとJSON解析エラーの両方を考慮する必要があります。

8-3. JSONを編集して保存するサンプル

JSONファイルを読み込み、値を変更して保存する例です。

C#
using System.Text.Json;

string path = "user.json";

string json = File.ReadAllText(path);

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

if (user != null)
{
user.Name = "Updated Taro";

var options = new JsonSerializerOptions
{
WriteIndented = true
};

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

File.WriteAllText(path, updatedJson);
}

一度C#のオブジェクトに変換してから編集し、再度JSONとして保存する流れです。設定画面で変更した内容をJSONファイルへ保存するような処理に応用できます。

8-4. 複数データをJSONで管理するサンプル

複数のユーザー情報をJSONで管理する例です。

JSON
[
{
"Id": 1,
"Name": "Taro",
"Email": "taro@example.com"
},
{
"Id": 2,
"Name": "Hanako",
"Email": "hanako@example.com"
}
]

C#ではList<User>として読み込みます。

C#
using System.Text.Json;

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

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

if (users != null)
{
users.Add(new User
{
Id = 3,
Name = "Sato",
Email = "sato@example.com"
});

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

File.WriteAllText("users.json", updatedJson);
}

小規模なデータ管理であれば、JSONファイルでも十分対応できます。ただし、データ件数が増える場合や同時更新が発生する場合は、データベースの利用を検討しましょう。

9. C#でJSONを扱う際のベストプラクティス

9-1. 型安全に扱うためにクラスを定義する

C#でJSONを扱うときは、できるだけクラスを定義して型安全に扱うのがおすすめです。

JsonDocumentdynamicを使うと柔軟にJSONを扱えますが、プロパティ名のミスや型の不一致に気づきにくくなります。クラスを定義しておけば、コンパイル時にミスを発見しやすくなり、コード補完も使いやすくなります。

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

長く保守するコードでは、JSONの構造をC#のクラスとして明確に表現することが大切です。

9-2. 例外処理を入れて安全に読み込む

JSONは外部ファイルやAPIから受け取ることが多いため、常に正しい形式とは限りません。読み込みや変換の処理には、例外処理を入れましょう。

C#
try
{
string json = File.ReadAllText("data.json");
User? user = JsonSerializer.Deserialize<User>(json);
}
catch (FileNotFoundException)
{
Console.WriteLine("ファイルが見つかりません。");
}
catch (JsonException)
{
Console.WriteLine("JSONの形式が正しくありません。");
}
catch (Exception ex)
{
Console.WriteLine($"予期しないエラー: {ex.Message}");
}

エラーが起きたときにアプリケーションが突然終了しないよう、想定される例外に対応しておきましょう。

9-3. 不要なプロパティを無視する

外部APIのJSONには、C#側で使わないプロパティが含まれていることがあります。基本的には、C#のクラスに存在しないプロパティは無視されます。

JSON
{
"Id": 1,
"Name": "Taro",
"UnusedValue": "abc"
}

C#側で必要なプロパティだけ定義しておけば、扱うデータをシンプルにできます。

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

ただし、API仕様が変わる可能性がある場合は、重要な項目が消えたり型が変わったりしていないかを確認する仕組みも必要です。

9-4. パフォーマンスを意識したJSON処理

大量のJSONを扱う場合は、パフォーマンスにも注意が必要です。

小さなJSONであれば、JsonSerializer.Deserializeでクラスに変換する方法が簡単です。しかし、非常に大きなJSONを扱う場合や、すべてのデータをメモリに載せたくない場合は、ストリーム処理や必要な部分だけを読む方法を検討します。

また、同じJsonSerializerOptionsを何度も使う場合は、毎回新しく作成するのではなく、再利用するのが望ましいです。Microsoftのドキュメントでも、同じオプションを複数回使う場合はJsonSerializerOptionsのインスタンスを再利用することが推奨されています。Microsoft Learn

C#
private static readonly JsonSerializerOptions JsonOptions = new()
{
PropertyNameCaseInsensitive = true,
WriteIndented = true
};

パフォーマンスが問題になる前から過度に最適化する必要はありませんが、大量データを扱う処理では意識しておきましょう。

9-5. 保守しやすいJSON設計のポイント

保守しやすいJSONを設計するには、キー名やデータ型を統一することが重要です。

たとえば、ある場所ではuserName、別の場所ではuser_name、さらに別の場所ではNameのように表記がばらばらだと、C#側の変換処理が複雑になります。

また、数値を文字列として扱う、日付形式が複数混在する、nullと空文字の意味が曖昧、といった設計もトラブルの原因になります。

JSON設計では、キー名の命名規則、日付形式、nullの扱い、配列とオブジェクトの構造をあらかじめ決めておくと、C#側の実装もシンプルになります。

10. C#のJSON処理に関するよくある質問

10-1. C#でJSONを扱うにはどのライブラリが必要か

新しいC#プロジェクトで基本的なJSON処理を行う場合は、System.Text.Jsonを使えば十分です。標準ライブラリとして利用できるため、追加パッケージなしでシリアライズやデシリアライズができます。

一方、既存プロジェクトでNewtonsoft.Jsonが使われている場合や、より柔軟なJSON操作が必要な場合は、Newtonsoft.Jsonを利用することもあります。

10-2. System.Text.JsonとNewtonsoft.Jsonの違いは何か

System.Text.Jsonは、.NET標準のJSON処理ライブラリです。基本的なJSONの読み込み、変換、出力をシンプルに実装できます。

Newtonsoft.Jsonは、長年使われてきた高機能なJSONライブラリです。JsonConvertを使った簡単な変換や、柔軟なカスタマイズに対応しています。公式ドキュメントでも、JsonSerializerが.NETオブジェクトをJSON相当へ変換し、JSONから.NETオブジェクトへ戻す機能を持つと説明されています。Newtonsoft

初心者はまずSystem.Text.Jsonを学び、必要に応じてNewtonsoft.Jsonも理解するとよいでしょう。

10-3. JSONをDictionaryに変換できるか

JSONはDictionary<string, TValue>に変換できます。キーと値の組み合わせとして扱いたい場合に便利です。

C#
using System.Text.Json;

string json = """
{
"name": "Taro",
"email": "taro@example.com"
}
""";

Dictionary<string, string>? dict =
JsonSerializer.Deserialize<Dictionary<string, string>>(json);

if (dict != null)
{
Console.WriteLine(dict["name"]);
}

ただし、値の型が文字列、数値、真偽値など混在している場合は、Dictionary<string, JsonElement>として扱う方法もあります。

C#
Dictionary<string, JsonElement>? dict =
JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);

型が明確なデータであればクラス、キーが動的に変わるデータであればDictionaryを使うとよいでしょう。

10-4. JSON配列をC#で読み込むにはどうすればよいか

JSON配列は、List<T>または配列にデシリアライズできます。

C#
string json = """
[
{ "Id": 1, "Name": "Taro" },
{ "Id": 2, "Name": "Hanako" }
]
""";

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

配列として受け取りたい場合は、次のように書きます。

C#
User[]? users = JsonSerializer.Deserialize<User[]>(json);

後から要素を追加・削除したい場合はList<T>、固定長で扱いたい場合は配列を使うとよいでしょう。

10-5. JSONを整形して出力するにはどうすればよいか

JSONを見やすく整形して出力するには、JsonSerializerOptionsWriteIndentedtrueにします。

C#
var options = new JsonSerializerOptions
{
WriteIndented = true
};

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

これにより、改行とインデントが入った読みやすいJSONを出力できます。設定ファイルやデバッグ用ログでは整形されたJSONが便利です。

まとめ

C#でJSONを扱うには、主にSystem.Text.JsonまたはNewtonsoft.Jsonを使います。新規開発では、まず標準ライブラリであるSystem.Text.Jsonを使うのがおすすめです。

JSONをC#で扱う基本は、JSON文字列をクラスに変換するデシリアライズと、C#のオブジェクトをJSON文字列に変換するシリアライズです。JSONファイルの読み込み、Web APIレスポンスの処理、設定情報の保存など、さまざまな場面で活用できます。

初心者は、まずJSONに対応するC#クラスを作成し、JsonSerializer.SerializeJsonSerializer.Deserializeの使い方を覚えましょう。そのうえで、JsonDocumentJsonElementを使った動的なJSON解析、プロパティ名の対応、例外処理、文字化け対策を学ぶと、実践的なJSON処理に対応できるようになります。