4

我试图从 json.net 迁移到微软的 json 并发现一些行为非常不同的东西。

让我们使用这个简化的例子:

public interface IName
{
    string Name { get; set; }

}

public class Person : IName
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public void Foo() 
{
   IName p = new Person {Age = 4, Name = "Waldo"};
   var s1 = System.Text.Json.JsonSerializer.Serialize(p); // --> {"Name":"Waldo"}
   var s2 = Newtonsoft.Json.JsonConvert.SerializeObject(p); // --> {"Name":"Waldo","Age":4}
}

Microsoft 的 Serializers 序列化来自 IName 的属性 JSON.NET 序列化来自 Person 的属性

有没有办法配置它,使它像 JSON.NET 一样工作?我可以通过的选项并不表明这是可配置的。我忽略了什么吗?

4

4 回答 4

5

这是因为序列化程序使用泛型参数的类型,而不是传递值的类型:

public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null)
{
    return WriteCoreString(value, typeof(TValue), options);
}

这传递typeof(IName)WriteCoreString,并在该类型上最终执行反射。

您可以通过将类型显式传递给接受以下内容的重载来解决此问题:

var s3 = System.Text.Json.JsonSerializer.Serialize(p, p.GetType());

这将返回:

{"Name":"Waldo","Age":4}

转换为object也可以,因为代码然后调用value.GetType()

var s4 = System.Text.Json.JsonSerializer.Serialize((object)p);
于 2019-10-17T09:39:35.757 回答
2

请参阅序列化派生类的属性

不支持多态类型层次结构的序列化。例如,如果一个属性被定义为接口或抽象类,那么即使运行时类型具有附加属性,也只会序列化接口或抽象类上定义的属性。本节说明了此行为的例外情况。

(此处为示例)

此行为旨在帮助防止意外暴露派生的运行时创建的类型中的数据。

进而:

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

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

    json = JsonSerializer.Serialize(weatherForecast, weatherForecast.GetType());

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

    json = JsonSerializer.Serialize<object>(weatherForecast);

于 2019-10-17T09:41:30.553 回答
2

Newtonsoft.Json.JsonConvert.SerializeObject是一种非泛型方法,因此它在运行时分析提供的对象并序列化该对象具有的所有属性。

相比之下System.Text.Json.JsonSerializer.Serialize(p),被解析为泛型方法。编译器根据变量的类型推断类型参数,在你相同的情况下IName。因此,该方法分析提供的类型并导出泛型类型参数的属性,而不是实现接口的对象的所有属性。

文档显示,serialize 方法总是需要通过泛型类型参数或作为方法的参数来指定类型。

以下代码应修复该行为:

var s1 = System.Text.Json.JsonSerializer.Serialize(p, p.GetType()); 
// --> {"Name":"Waldo","Age":4}

请参阅此示例

于 2019-10-17T09:41:31.970 回答
0

我认为您需要将对象的引用传递给方法

        IName p = new Person { Age = 4, Name = "Waldo" };
        var s1 = System.Text.Json.JsonSerializer.Serialize<Person>((Person)p);

对于 .NET Core 3.0

于 2019-10-17T09:40:41.603 回答