0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

.NET10:JSONシリアル化時に自分を参照する問題の解決

Posted at

現在のビジネスシナリオとして、雇員クラスがあり、その中に管理者という属性があり、それも同じ雇員クラスのタイプです。通常の雇員の管理者はマネージャー、マネージャーの管理者はCEOであり、CEOの管理者は空か自分自身を管理しています。空は正常ですが、もしCEOの管理者が自分自身の場合、.NET9では以下のように実現します:

using System.Text.Json;

var ceo = new Employee { NO = 1, Name = "CEO" };
ceo.Manager = ceo;  // ここでエラーが発生
Console.WriteLine(JsonSerializer.Serialize(ceo));
Console.WriteLine("---------------");

var manager = new Employee { NO = 2, Name = "Manager" };
manager.Manager = ceo;
Console.WriteLine(JsonSerializer.Serialize(manager));
Console.WriteLine("---------------");

var employee = new Employee { NO = 3, Name = "Employee" };
employee.Manager = manager;
Console.WriteLine(JsonSerializer.Serialize(employee));

class Employee
{
    public int NO { get; set; }
    public string? Name { get; set; }
    public Employee? Manager { get; set; }
}

実行すると、循環参照の例外が発生します:

画像

源生成器を用いてJSONシリアル化を行う場合、生成されるコンテキストは循環参照でシリアル化やデシリアル化を行う際に例外をスローします。今では、JsonSourceGenerationOptionsAttributeにおいてReferenceHandlerを指定することでこの動作をカスタマイズすることができます。以下は、JsonKnownReferenceHandler.Preserveを使用した例です:

using System.Text.Json;
using System.Text.Json.Serialization;

var ceo = new Employee { NO = 1, Name = "CEO" };
ceo.Manager = ceo;
Console.WriteLine(JsonSerializer.Serialize(ceo, ContextWithPreserveReference.Default.Employee));
Console.WriteLine("---------------");

var manager = new Employee { NO = 2, Name = "Manager" };
manager.Manager = ceo;
Console.WriteLine(JsonSerializer.Serialize(manager, ContextWithPreserveReference.Default.Employee));
Console.WriteLine("---------------");

var employee = new Employee { NO = 3, Name = "Employee" };
employee.Manager = manager;
Console.WriteLine(JsonSerializer.Serialize(employee, ContextWithPreserveReference.Default.Employee));
Console.ReadLine();

[JsonSourceGenerationOptions(ReferenceHandler = JsonKnownReferenceHandler.Preserve)]
[JsonSerializable(typeof(Employee))]
internal partial class ContextWithPreserveReference : JsonSerializerContext
{
}
class Employee
{
    public int NO { get; set; }
    public string? Name { get; set; }
    public Employee? Manager { get; set; }
}

実行結果は以下の通りです:

画像

(Translated by GPT)
元のリンク:https://mp.weixin.qq.com/s/GLdh4ZHzNVz3xqeEenqG9g?token=1135395277&lang=zh_CN&wt.mc_id=MVP_325642

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?