System.Text.JsonでJSONをキャメルケースでシリアライズする


はじめに

昔、Newtonsoft.Jsonがあった(いまもある)。
Newtonsoft.Jsonは、変換が柔軟な反面、パフォーマンス等が犠牲になっている。

しかし、常に柔軟さが必要なわけではない。
変換が厳密でいい場合に、Newtonsoft.Jsonの機能は過剰であるから、よりパフォーマンスに優れたライブラリSystem.Text.Jsonが作られた。

柔軟とはどういうことか?
例えば、Newtonsoft.Jsonでは、JSONのnameというキーがあったとき、これはC#のNameプロパティにデシリアライズできる。
System.Text.Jsonではデフォルトではこれはできない。
でも、JSONのキーはキャメルケースにしたいじゃん?

めんどくさい方法

C#のプロパティがどういう風にシリアライズされるか、は、プロパティごとに属性で定義できる。

個別に設定するめんどくさい方法
public class Model
{
    [JsonPropertyName("name")]
    public string Name { get; set; }
}

これで自由にキー名をコントロールできる。
が、プロパティが多いと、全部にこれを指定するのはめんどくさすぎる。

簡単な方法

キャメルケースにしたい!と決まっている場合は、わざわざプロパティにJsonPropertyName属性を指定せずとも、変換時の設定で一括でできる。

一括設定する方法
var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
var json = JsonSerializer.Serialize(model, options);

プロパティについてるJsonPropertyName属性が優先されるので、基本はキャメルケースだけどこれだけ別の指定…もできる。

もっと簡単な方法

Webでいい感じに使える、なんか、デフォルトの設定は無いの?→あります

WEBのデフォルト設定を通過う方法
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
var json = JsonSerializer.Serialize(model, options);

デフォルト設定としてJsonSerializerDefaults.Webを指定すると、以下の設定がされる。

  • シリアライズがキャメルケースになる
  • デシリアライズ時にキーの大文字小文字が区別されなくなる
  • デシリアライズ時に数値がダブルクオーテーションで囲まれていても良くなる

おまけ:自分がよく使う設定

おまけ
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    //DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    //WriteIndented = true,
};
var json = JsonSerializer.Serialize(model, options);
  • Web設定をベースにしつつ…
  • Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
    • 値のエスケープをゆるゆるにする。
    • これをしないと、日本語もエスケープされて、読めなくなる。
      • {"name":"\u3053\u3093\u306B\u3061\u306F"}
    • 指定するとこう↓
      • {"name":"こんにちは"}
  • DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
    • 値がnullになってるプロパティを、JSONに含めなくする。
    • デフォルトでは{"name":null}みたいになるけど、これを付けておくと値がnullの場合は項目ごと無くなる。→{}
    • 適宜つける。
  • WriteIndented = true
    • 出力をインデントする。
    • デバッグの時だけつける。