標準で搭載されている System.Text.Json
名前空間の JsonSerializer
クラスを使って、JSONのシリアライズやデシリアライズを行う方法を解説します。
環境
- Visual Studio 2022
- .NET 8
参考ドキュメント
前提
JSONシリアライズとは、C#のオブジェクトをJSON形式の文字列に変換(シリアル化)することで、JsonSerializer
クラスの Serialize
メソッドを使用します。
一方JSONデシリアライズはシリアライズの逆で、JSON形式の文字列をC#のオブジェクトに変換(非シリアル化)することを指し、JsonSerializer
クラスの Deserialize
メソッドを使用します。
以下では、コンソールアプリを用いてこれらの使い方を説明します。
サンプルクラスの定義
まずJSONへのシリアライズとデシリアライズに使用するサンプルクラスを用意します。
JSON関係の属性を付与するため、using
に System.Text.Json.Serialization
を追加しています。
using System.Text.Json.Serialization;
internal class Person
{
[JsonPropertyName("Name")]
public string? FullName { get; set; }
public int Age { get; set; }
public string? FavoriteThings { get; set; }
[JsonIgnore]
public string? Memo { get; set; }
}
プロパティに付与している属性について説明します。
JsonPropertyName属性
シリアライズまたはデシリアライズ時に、プロパティ名を指定した名前に変換することができます。
後に説明する名前付けポリシーよりも優先して適用されます。
JsonIgnore属性
通常はすべてのpublicプロパティがJSON化されますが、この属性を付与するとそのプロパティを対象から除外することができます。
さらに細かく条件を指定して除外することもできるので、気になる方はドキュメントを確認してみてください。
JSONのシリアライズ・デシリアライズ
Program.cs
にシリアライズとデシリアライズを行う処理を記述します。
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
// オプション設定
var options = new JsonSerializerOptions
{
// 日本語を変換するためのエンコード設定
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
// (.NET 8以降)プロパティ名をスネークケースに変換
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
// (.NET 7以前)プロパティ名をスネークケースに変換するための自作ポリシーを適用
//PropertyNamingPolicy = new SnakeCaseNamingPolicy(),
// インデントを付ける
WriteIndented = true
};
var person = new Person
{
FullName = "田中太郎",
Age = 20,
FavoriteThings = "読書",
Memo = "こんにちは"
};
// シリアライズ
var jsonString = JsonSerializer.Serialize(person, options);
Console.WriteLine(jsonString);
// デシリアライズ
var person2 = JsonSerializer.Deserialize<Person>(jsonString, options);
Console.WriteLine($"{person2?.FullName} {person2?.Age} {person2?.FavoriteThings}");
最初にJsonSerializer
のオプション設定を行っています。よく使いそうなオプションについて説明します。
Encoder
日本語がUnicodeエスケープシーケンスに変換(例:あ → \u3042
)されるのを防ぐため、日本語が含まれる場合は必ず「JavaScriptEncoder.Create(UnicodeRanges.All)
」と指定します。
PropertyNamingPolicy
名前付けポリシーを指定することができます。
例えば「JsonNamingPolicy.CamelCase
」を指定すると、シリアライズ時に全てのプロパティ名をキャメルケースに変換してくれます。
また、PropertyNamingPolicy
には自作のポリシーを指定することもできます。
.NET 7以前の場合はスネークケースに変換するための名前付けポリシーが用意されていないので、ポリシーを自作して指定する必要があります。(詳細は後述)
WriteIndented
trueにするとJSON出力時にインデントが付与されて見やすくなります。
他にも色々なオプションがあるので、こちらも詳細はドキュメントを確認してください。
JSONのシリアライズ・デシリアライズ
シリアライズするには、JSON化したいデータとオプションを JsonSerializer
クラスの Serialize
メソッドの引数に指定します。
デシリアライズは、Deserialize<T>
メソッドの引数にJSONデータとオプションを指定します。
<T>
にはバインドしたい型を指定します。今回はPersonクラスを指定しました。
実行結果
名前付けポリシーやJsonPropertyName
属性によって、シリアライズ時にプロパティ名が指定通りに変更されていることが確認できます。
(.NET 7 以前)カスタム名前付けポリシー
.NET 7 以前のバージョンを使用している場合は、スネークケースに変換するためには名前付けポリシーを自作する必要があります。
参考までにポリシーの実装を紹介します。
using System.Text.Json;
using System.Text.RegularExpressions;
/// <summary>
/// スネークケース命名ポリシー
/// </summary>
internal class SnakeCaseNamingPolicy : JsonNamingPolicy
{
/// <summary>
/// プロパティ名をスネークケースに変換する
/// </summary>
/// <param name="name">変換前のプロパティ名</param>
/// <returns>変換後のプロパティ名</returns>
public override string ConvertName(string name)
{
var pattern = "[a-z][A-Z]";
MatchEvaluator evaluator = m => m.Groups[0].Value[0] + "_" + m.Groups[0].Value[1];
return Regex.Replace(name, pattern, evaluator).ToLower();
}
}
カスタムポリシーはJsonNamingPolicy
抽象クラスを継承し、ConvertName
メソッドをオーバーライドすることで作成することができます。
ここでは正規表現を用いてパスカルケースのプロパティ名をスネークケースに変換しています。
おすすめ書籍
JsonSerializer
の基本的な使い方などが紹介されています。