C# 为什么System.Text Json Serialiser不序列化此泛型属性,而Json.NET序列化此泛型属性?

C# 为什么System.Text Json Serialiser不序列化此泛型属性,而Json.NET序列化此泛型属性?,c#,.net-core,json.net,system.text.json,C#,.net Core,Json.net,System.text.json,我有以下情况。我已将问题简化为以下示例,尽管我的实际情况更为复杂 System.Text.Json不会完全序列化对象,但Newtonsoft Json.NET会 假设我有下面的类结构 public class A { public string AProperty { get; set; } = "A"; } public class A<T> : A where T : class, new() { public T TObject { get; set; } =

我有以下情况。我已将问题简化为以下示例,尽管我的实际情况更为复杂

System.Text.Json不会完全序列化对象,但Newtonsoft Json.NET

假设我有下面的类结构

public class A
{
    public string AProperty { get; set; } = "A";
}

public class A<T> : A where T : class, new()
{
    public T TObject { get; set; } = new T();
}

public class B
{
    public string BProperty { get; set; } = "B";
}

public class B<T> : B where T : class, new()
{
    public T TObject { get; set; } = new T();
}

public class C
{
    public string CProperty { get; set; } = "C";
}
纽顿软件 由于我的应用程序的结构,我不知道
B
的泛型参数。我只知道它是一个
A
B
的实际
TObject
直到运行时才知道


为什么这两种序列化方法不同?有没有办法让System.Text.Json完全序列化对象,或者我需要编写一个自定义转换器?

这是
System.Text.Json
的一个文档限制。从:

序列化派生类的属性

不支持多态类型层次结构的序列化。例如,如果将属性定义为接口或抽象类,则即使运行时类型具有其他属性,也仅序列化在接口或抽象类上定义的属性。此行为的例外情况将在本节中进行解释。。。。

要序列化[a]派生类型的属性,请使用以下方法之一:

  • 调用Serialize的重载,该重载允许您在运行时指定类型

  • 将要序列化的对象声明为
    对象

  • 在您的例子中,
    A.TObject
    被声明为类型
    B
    ,但在您构造的实例中实际上是类型
    B
    ,因此只有基类
    B
    的属性按照文档进行序列化。就这样。有关进一步讨论,请参阅已结束的问题

    然而,有几种变通方法可用。首先,您可以将
    obj
    构造为其最可能的派生类型
    A

    var obj=newa{TObject=newb()};
    
    现在,
    TObject
    的所有属性都被序列化。演示小提琴#1。但不幸的是,您无法使用此解决方法,因为
    B
    的实际
    TObject
    直到运行时才知道

    或者,如果您只需要序列化您的
    obj
    ,您可以按照文档中的建议2,声明一个
    对象类型的代理属性,并序列化:

    public class A:A其中T:class,new()
    {
    [System.Text.Json.Serialization.JsonPropertyName(“TObject”)]
    [Newtonsoft.Json.JsonIgnore]
    公共对象SerializedObject=>ToObject;
    [System.Text.Json.Serialization.JsonIgnore]
    公共T TObject{get;set;}=new T();
    }
    
    请注意,不能为要序列化的只读属性设置

    演示小提琴2

    最后,如果需要多态序列化和反序列化,则需要编写一个自定义的。开始看


    您可以编写自定义转换器或等待.NET 5发布,因为JSON.NET要好得多
    public class Program
    {
        private static void Main(string[] args)
        {
            var obj = new A<B> { TObject = new B<C>() };
    
            var systemTextSerialized = JsonSerializer.Serialize(obj);
            var newtonsoftSerialized = JsonConvert.SerializeObject(obj);
        }
    }
    
    {
      "TObject": {
        "BProperty": "B"
      },
      "AProperty": "A"
    }
    
    
    {
      "TObject": {
        "TObject": {
          "CProperty": "C"
        },
        "BProperty": "B"
      },
      "AProperty": "A"
    }