CodeGym /コース /C# SELF /Newtonsoft.Json の使い方

Newtonsoft.Json の使い方

C# SELF
レベル 44 , レッスン 4
使用可能

1. はじめに

Newtonsoft.Json は良い意味でいうと一種の「恐竜」だ。事実上の標準として長年 .NET エコシステムで JSON を扱ってきて、System.Text.Json が出てくる前から広く使われてきた。何百万ものプロジェクト、何千ものライブラリやフレームワーク(最近まで ASP.NET Core の多くの部分も含む)が Json.NET を使っている。

利点は次の通り:

  • 機能が豊富で柔軟:Json.NET はシリアライズ/デシリアライズのプロセスをカスタマイズするための多数の設定、属性、機能を提供する。System.Text.Json が苦労する、あるいはできないこともこなせる。
  • 「完璧でない」JSON に寛容:外部システムから来るデータは常に綺麗とは限らない — Json.NET はそうしたケースに比較的寛容で、余計な手間なくデシリアライズできることが多い。
  • 後方互換性がある:プロジェクトやライブラリが Json.NET に依存しているなら、それを扱えるスキルは依然として必要だ。

もちろん、System.Text.Json の方が高速で現代的な要件を念頭に作られている。でも、特定のロジックや最大限の柔軟性が必要な場面では Newtonsoft.Json がいまだに強力なツールだよ。

Newtonsoft.Json をどうやって導入する?

これはサードパーティのライブラリなので、NuGet でパッケージを追加してね:

  1. プロジェクトを開く。
  2. Solution Explorer でプロジェクトを右クリック。
  3. “Manage NuGet Packages...” を選択。
  4. 検索ボックスに Newtonsoft.Json と入力。
  5. パッケージを選んで「Install」をクリック。

インストール後は依存関係が追加されて、Json.NET を使えるようになるよ!

Newtonsoft.JsonSystem.Text.Json の機能比較

機能 System.Text.Json Newtonsoft.Json
簡単なシリアライズ/デシリアライズ はい はい
プロパティ用属性のサポート 部分的に 完全
カスタムコンバーター はい はい
プライベートフィールドの扱い いいえ はい
動的な構造の扱い 制限あり はい
LINQ to JSON (JObject/JArray) いいえ はい
Reference Loop Handling はい はい
DataTable, DataSet と複雑な型のサポート いいえ はい
パフォーマンス 優れている 良い

2. 単純オブジェクトのシリアライズとデシリアライズの例

ここではレクチャーで使う一般的なゲーム構造を取り上げる:

public class Player
{
    public string Name { get; set; }
    public int Health { get; set; }
    public bool IsAlive { get; set; }
    public List<string> Inventory { get; set; }
    public Position Position { get; set; }
}

public class Position
{
    public int X { get; set; }
    public int Y { get; set; }
}

では Player オブジェクトを JSON に保存して復元しよう:

using Newtonsoft.Json;

Player player1 = new Player
{
    Name = "Aragorn",
    Health = 100,
    IsAlive = true,
    Inventory = new List<string> { "sword", "bow", "healing potion" },
    Position = new Position { X = 10, Y = 25 }
};

// JSON 文字列へのシリアライズ
string json = JsonConvert.SerializeObject(player1, Formatting.Indented);
Console.WriteLine(json);

// 逆に Player オブジェクトへデシリアライズ
Player player2 = JsonConvert.DeserializeObject<Player>(json);
Console.WriteLine($"名前: {player2.Name}, 体力: {player2.Health}");

全部?まあ、ほとんどだけど、これは氷山の一角に過ぎない。Newtonsoft.Json が他のライブラリよりどう面白くて柔軟なのか見ていこう。

3. フォーマット、設定、拡張パラメータ

オブジェクトをシリアライズするとき、コンパクトな文字列にも見やすく整形された JSON にもできる。振る舞いはパラメータや設定で制御できるよ。

例: フォーマットのいくつかのパターン

// 見やすい整形された JSON
string prettyJson = JsonConvert.SerializeObject(player1, Formatting.Indented);

// コンパクトな(ミニファイド)JSON
string compactJson = JsonConvert.SerializeObject(player1, Formatting.None);

シリアライズ設定

必要なら JsonSerializerSettings を渡して細かく設定できる:

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore, // null 値のフィールドをスキップ
    DefaultValueHandling = DefaultValueHandling.Ignore, // デフォルト値のフィールドをスキップ
    Formatting = Formatting.Indented
};
string customJson = JsonConvert.SerializeObject(player1, settings);

出力フォーマットを最大限コントロールできる:空のフィールドを飛ばしたければその通りにできるし、プライベートなプロパティまでシリアライズしたければ契約(contract)を調整すればいい。

4. 属性によるフィールドとプロパティの制御

Newtonsoft.Json はクラス内でシリアライズを調整するための強力な属性をサポートしている。

JsonProperty — プロパティ名の変更

JSON プロトコルが別名を要求する場合:

public class Player
{
    [JsonProperty("player_name")]
    public string Name { get; set; }
    // ...
}

生成される JSON の例:

{ "player_name": "Aragorn", ... }

JsonIgnore — プロパティを無視する

public class Player
{
    [JsonIgnore]
    public int Health { get; set; }
}

これで Health フィールドはシリアライズ時に消える。

JsonConverter — カスタム変換

特定のフィールドをどのコンバーターで処理するか指定できる。

public class Player
{
    [JsonConverter(typeof(InventoryToStringConverter))]
    public List<string> Inventory { get; set; }
}

(コンバーターの詳細は下で説明するよ。)

5. ネストされたオブジェクトとコレクションの扱い

Json.NET はネストされたオブジェクトや配列、コレクション、辞書を得意とする。

例: 辞書 (Dictionary)

public class GameStats
{
    public Dictionary<string, int> Scores { get; set; }
}

GameStats stats = new GameStats
{
    Scores = new Dictionary<string, int>
    {
        ["Alice"] = 1023,
        ["Bob"] = 999
    }
};

string statsJson = JsonConvert.SerializeObject(stats, Formatting.Indented);
Console.WriteLine(statsJson);

生成される JSON は次のようになる:

{
  "Scores": {
    "Alice": 1023,
    "Bob": 999
  }
}

6. 複雑な構造: 循環参照、Self-Referencing Objects

時々オブジェクト同士が相互参照していることがある。Newtonsoft.Json は専用の設定を使ってこうした構造のシリアライズをサポートしている。

例: 循環参照の解決

public class Person
{
    public string Name { get; set; }
    public Person Parent { get; set; }
    public List<Person> Children { get; set; }
}

// 循環のためにシリアライズ設定をする
var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore // または .Serialize
};

Person p1 = new Person { Name = "パパ" };
Person p2 = new Person { Name = "息子", Parent = p1 };
p1.Children = new List<Person> { p2 };

string json = JsonConvert.SerializeObject(p1, settings);
Console.WriteLine(json);

デフォルトで ReferenceLoopHandling = Error にしておくと例外が投げられる。意図しない無限シリアライズを防ぐための保護だよ。

7. 動的構造の扱い: JObject, JArray

JSON の構造が事前にわからない、あるいは実行時に変わる場合は、C# の強い型付けを使わずに動的に扱う方が楽なことがある。

主な型:

  • JObject — JSON オブジェクトの表現。
  • JArray — 配列の表現。
using Newtonsoft.Json.Linq;

// 文字列を JObject にパース
string json = @"{ 'name': 'Aragorn', 'health': 100 }";
JObject obj = JObject.Parse(json);

Console.WriteLine((string)obj["name"]); // Aragorn
Console.WriteLine((int)obj["health"]);  // 100

// 動的にプロパティを追加
obj["class"] = "Ranger";
Console.WriteLine(obj.ToString());

配列のイテレーション

string jsonArr = @"['apple', 'banana', 'cherry']";
JArray array = JArray.Parse(jsonArr);

foreach (JToken item in array)
{
    Console.WriteLine(item);
}

8. バージョニングと必須フィールドのサポート

JSON フォーマットは進化するし、フィールドが欠けることもある。属性や設定を使って対応しよう:

  • [JsonProperty(Required = Required.Always)] — フィールドの存在を必須にする(なければ例外)。
  • [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] — フィールドがない場合にデフォルトを入れる。
public class Player
{
    [JsonProperty(Required = Required.Always)]
    public string Name { get; set; }

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
    [DefaultValue(50)]
    public int Health { get; set; }
}

9. 日付と時間フォーマットの変換

日付を扱うときは明示的なフォーマットが必要になることが多い。

var dateSettings = new JsonSerializerSettings
{
    DateFormatString = "yyyy-MM-dd"
};
string json = JsonConvert.SerializeObject(DateTime.Now, dateSettings);
Console.WriteLine(json); // "2024-06-15"

逆にデシリアライズする場合:

string dateJson = "\"2024-06-15\""; // 注意: これは引用符で囲まれた文字列だよ!
DateTime dt = JsonConvert.DeserializeObject<DateTime>(dateJson);
Console.WriteLine(dt);
1
アンケート/クイズ
標準シリアライズクラス、レベル 44、レッスン 4
使用不可
標準シリアライズクラス
シリアライズ用のクラスとライブラリ
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION