簡體   English   中英

Select 類型用於 System.Text.Json 中的反序列化

[英]Select type to use for deserialization in System.Text.Json

我有一個 .NET 6 應用程序需要反序列化一些 JSON 數據到 C# 對象,使用System.Text.Json

但是,在我試圖反序列化的類中,我有一個經典案例,其中屬性具有基類類型,如下所示:

public class ClassToDeserialize
{
    public JobBase SomeJob { get; set; }
}

public class JobBase
{
    public string JobName { get; set; }
}

需要反序列化為正確的派生類型,例如:

public class OnDemandJob : JobBase
{
    public string RequestUser { get; set; }
}

public class ScheduledJob: JobBase
{
    public string Schedule { get; set; }
}

我想做的是編寫一個自定義轉換器,它檢查 JSON 數據以決定使用哪種類型進行反序列化(例如,在上面的示例中,我們可以通過檢查是否存在實際的ScheduledJob數據中的Schedule屬性),然后反序列化為該類型。

現在,閱讀官方文檔,我很高興地發現微軟想到了這一點,並且有一篇文章,其中包含一個關於如何使用轉換器實現此場景的示例:

https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-6-0#support-polymorphic-deserialization

但是我的問題是這樣的:對我來說,他們在示例中實現的轉換器對於它需要做的事情來說似乎過於復雜。 特別是,他們在找到正確的類型后所做的是“手動”通過創建實例並手動讀取 JSON 數據並將屬性一個接一個地分配給 ZA8CFDE6331BD59EB2AC96F8911C4B666 來“手動”構建正確的派生 object。

對於我想要實現的目標,這似乎需要大量的手動工作。 直覺上,我認為應該可以做這樣的事情(偽代碼):

public JobBase Read(...)
{
    if(jsonObject.HasProperty("Schedule")
    {
        return JsonSerializer.Deserialize<ScheduledJob>(jsonString);
    }
    else 
    {
        return JsonSerializer.Deserialize<OnDemandJob>(jsonString);
    }
}

這樣的事情可能嗎? 還是我真的必須逐個字段手動構建整個 object?

感謝@dbc 為我指明了正確的方向,這是我最終得到的轉換器:

public class JobBaseConverter : JsonConverter<JobBase>
{
    public override JobBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            throw new JsonException();
        }

        using (var jsonDocument = JsonDocument.ParseValue(ref reader))
        {
            if (jsonDocument.RootElement.TryGetProperty(nameof(ScheduledJob.Schedule), out var typeProperty))
            {
                return JsonSerializer.Deserialize<ScheduledJob>(jsonObject, options);
            }
            else
            {
                return JsonSerializer.Deserialize<OnDemandJob>(jsonObject, options);
            }
        }
    }

    public override void Write(Utf8JsonWriter writer, JobBase value, JsonSerializerOptions options)
    {
        if(value is ScheduledJob)
        {
            JsonSerializer.Serialize(writer, value as ScheduledJob, options);
        }
        else
        {
            JsonSerializer.Serialize(writer, value as OnDemandJob, options);
        }
    }
}

暫無
暫無

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

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