簡體   English   中英

當特定的 class 被強制轉換為其他東西時,JsonSerializer 的行為不符合預期

[英]JsonSerializer behaves not as expected when the specifc class is casted to something else

我試圖從 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 一樣工作? 我可以通過的選項並不表明這是可配置的。 我忽略了什么嗎?

這是因為序列化程序使用泛型參數的類型,而不是傳遞值的類型:

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);

請參閱序列化派生類的屬性

不支持多態類型層次結構的序列化。 例如,如果屬性定義為接口或抽象 class,則即使運行時類型具有附加屬性,也只會序列化接口或抽象 class 上定義的屬性。 本節說明了此行為的例外情況。

(此處為示例)

此行為旨在幫助防止意外暴露派生的運行時創建的類型中的數據。

接着:

要序列化派生類型的屬性,請使用以下方法之一:

  • 調用允許您在運行時指定類型的 Serialize 重載:

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

  • 將 object 聲明為 object。

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

Newtonsoft.Json.JsonConvert.SerializeObject是一種非泛型方法,因此它會在運行時分析提供的 object 並序列化 ZA8CFDE6331BD59EB2AC96F8911C4B666 的所有屬性。

相比之下System.Text.Json.JsonSerializer.Serialize(p)被解析為通用方法 對於相同的IName ,編譯器會根據變量的類型推斷類型參數。 因此,該方法分析提供的類型並導出泛型類型參數的屬性,而不是實現該接口的 object 的所有屬性。

文檔顯示,serialize 方法總是需要通過泛型類型參數或作為方法的參數來指定類型。

以下代碼應修復該行為:

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

請參閱此示例

我認為您需要將 object 的引用傳遞給該方法

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

適用於 .NET 核心 3.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM