【C#】System.Text.Jsonの使い方

System.Text.Jsonは .NET Core 3.0以降では標準で用意されています。
それより以前のバージョンでは下記の場合にパッケージをインストールすることで利用することが可能です。

  • .NET Standard 2.0 以降のバージョン
  • .NET Framework 4.7.2 以降のバージョン
  • .NET Core 2.0、2.1、および 2.2

【検証環境】.NET 5.0

クラスの定義

サンプルコードで使うPersonクラスを定義します。

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

class Person
{
    [JsonProperty("name")]   
    public string Name { get; set; }
    [JsonProperty("age")]
    public int Age { get; set; }
    [JsonProperty("height")]
    public int Height { get; set; }

    public static Person GetPerson()
    {
        return new Person()
        {
            Name = "本田翼",
            Age = 28,
            Height = 166,
        };
    }
    public static List<Person> GetPepople()
    {
        return new List<Person>()
        {
            new Person()
            {
                Name = "永野芽郁",
                Age = 21,
                Height = 163,
            },
            new Person()
            {
                Name = "本田翼",
                Age = 28,
                Height = 166,
            },
            new Person()
            {
                Name = "戸田恵梨香",
                Age = 32,
                Height = 164,
            },
        };
    }
}

使い方

基本的にはJson.NETと似たような雰囲気で使えるようです。

https://docs.microsoft.com/ja-jp/dotnet/standard/serialization/system-text-json-overview

シリアライズ

var jsonString = JsonSerializer.Serialize(Person.GetPerson());
Console.WriteLine(jsonString);
//[{"name":"u6C38u91CEu82BDu90C1","age":21,"height":163},{"name":"u672Cu7530u7FFC","age":28,"height":166},{"name":"u6238u7530u6075u68A8u9999","age":32,"height":164}]

上記の結果の様に、日本語の場合は文字化けしてしまいます。
JsonSerializerOptionsを生成して、第2引数に渡す必要があります。また、インデントを整形するためにWriteIndentedをtrueにします。

using System.Text.Encodings.Web;
using System.Text.Unicode;

var options = new JsonSerializerOptions
{
    //日本語の場合の文字化け防止
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
  //インデント整形
  WriteIndented = true,
};
var jsonString = JsonSerializer.Serialize(Person.GetPerson(), options);
Console.WriteLine(jsonString);
//[
//  {
//    "name": "永野芽郁",
//    "age": 21,
//    "height": 163
//  },
//  {
//    "name": "本田翼",
//    "age": 28,
//    "height": 166
//  },
//  {
//    "name": "戸田恵梨香",
//    "age": 32,
//    "height": 164
//  }
//]

本稿では実行結果を見やすくするためにWriteIndentedをtrueにしてJSONのインデントを整形しますが、実際に業務等で扱う場合はパフォーマンスの低下を防ぐため規定値のfalseにしてください。

File.WriteAllText(@"D:CSharptest.json", jsonString);

デシリアライズ

var people = JsonSerializer.Deserialize<List<Person>>(jsonString);
var jsonString = File.ReadAllText(@"D:CSharptest.json");
var people = JsonSerializer.Deserialize<List<Person>>(jsonString);

個々のプロパティの設定

一部のプロパティを出力しない

既定ではすべてのプロパティがシリアル化されますが、一部だけシリアル化させないためにはJsonIgnore属性を使用します。
PersonクラスのHeightプロパティに設定してみると、出力されなくなりました。

class Person
{
    [JsonPropertyName("name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]  //追加
    public string Name { get; set; }
    [JsonPropertyName("age")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]  //追加
    public int Age { get; set; }
    [JsonPropertyName("height")]
    <span class="fz-14px">[JsonIgnore]</span>  //追加
    public int Height { get; set; }
}

//[
//  {
//    "name": "永野芽郁",
//    "age": 21
//  },
//  {
//    "name": "本田翼",
//    "age": 28
//  },
//  {
//    "name": "戸田恵梨香",
//    "age": 32
//  }
//]

JsonIgnore属性のConditionプロパティを設定することによって、条件付き除外を指定できます。

Always(規定値) プロパティを常に出力しない
Never グローバル設定に関係なく、常にシリアル化および逆シリアル化する
WhenWritingDefault プロパティが規定値の場合、シリアル化しない
WhenwritingNull プロパティが参照型またはnull許容型で値がnullの場合、シリアル化しない

名前付けポリシー

本稿では最初にモデルのプロパティにJsonPropertyName属性を設定してプロパティ名を小文字で設定しています。
プロパティ数が多いと面倒になりますが、名前付きポリシーを利用すると一つ一つのプロパティに小文字でJsonPropertyName属性を設定する必要が無くなります。(※JsonPropertyName属性の方が優先されます。)

//名前付きポリシークラスの定義
public class LowerCaseNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name) => name.ToLower();
}

static void Main(string[] args)
{
    var options = new JsonSerializerOptions
    {
        //プロパティ名ポリシー設定
        PropertyNamingPolicy = new LowerCaseNamingPolicy(),
        //日本語の場合の文字化け防止
        Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
        //インデント整形
        WriteIndented = true,
    };
    var jsonString = JsonSerializer.Serialize(Person.GetPerson(), options);
    Console.WriteLine(jsonString);
}

Leave a Reply

Your email address will not be published. Required fields are marked *