簡體   English   中英

Json.Net反序列化為C#派生類

[英]Json.Net deserialize into C# derived class

Json.Net 不會將接收到的對象反序列化為Control類的適當派生類。 (請參閱下面對問題的解釋。另外請注意,我認為這是解釋問題所需的最少代碼量。感謝您提前審查此問題。)

我正在嘗試將以下類序列化/反序列化為JSON。

public class Page {
    public Guid Id { get; set; }
    public Guid CustomerId { get; set; }
    public IList<Control> Controls { get; set; }
}

這是Control類:

public class Control : ControlBase
{
    public override Enums.CsControlType CsControlType { get { return Enums.CsControlType.Base; } }
}

這是ControlBase抽象類:

public abstract class ControlBase
{
    public Guid Id { get; set; }

    public virtual Enums.CsControlType CsControlType { get; }

    public Enums.ControlType Type { get; set; }

    public string PropertyName { get; set; }

    public IList<int> Width { get; set; }

    public string FriendlyName { get; set; }

    public string Description { get; set; }
}

這是從Control派生的OptionsControl:

public class OptionsControl : Control
{
    public override Enums.CsControlType CsControlType { get { return Enums.CsControlType.OptionsControl; } }

    public IDictionary<string, string> Options;
}

將OptionsControl序列化后,JSON如下所示。 請注意,Json.Net添加了$type屬性,因此(據說)它可以將控件反序列化為OptionsControl。

              {  
                 "options":{  
                    "TN":"TN"
                 },
                 "csControlType":4,
                 "id":"00000000-0000-0000-0000-000000000000",
                 "type":4,
                 "propertyName":"addresses[0].state",
                 "width":[  
                    2,
                    2,
                    6
                 ],
                 "friendlyName":"State",
                 "description":null,
                 "$type":"MyApp.Infrastructure.Core.Models.UI.Controls.OptionsControl, MyApp.Infrastructure.Core"
              }

但是,當我嘗試反序列化Page(包含基本Controls和OptionsControls)時,所有控件都反序列化到基本Control中,而options屬性(包括上面的狀態列表)被忽略。

這是我嘗試反序列化(和更新)通過WebAPI服務收到的Page對象的方式:

    [HttpPut]
    [ActionName("UpdatePage")]
    public async Task<CommandResult> UpdatePageAsync([FromBody]Object page)
    {
        try
        {
            // Deserialize the page into the correct object
            // When I Debug.WriteLine the page.ToString(), the page still has the $type property at this point (before it is deserialized).
            var dsPage = return JsonConvert.DeserializeObject<Page>(page.ToString(), new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.All
            });

            // The dsPage passed in here does not have any OptionsControls.
            // At this point, they have all been deserialized into the base Control, unfortunately.
            return await _uiCommandFacade.UpdatePageAsync(dsPage, msg);
        }
        catch (Exception ex)
        {
            return new CommandResult()
            {
                ErrorType = ErrorType.ControllerError,
                DeveloperMessage = $"Unable to update page",
                Exception = ex
            };
        }
    }

如您所見,我使用TypeNameHandling.All(如文檔中所述,並在SO上多次提到)進行反序列化(就像我在序列化期間一樣,這就是在JSON中生成$type屬性的方式)。 但是,當我反序列化Page對象時,Page對象中的所有OptionsControl反序列化為常規的基本Control ,因此會忽略Options屬性(因此不會更新/丟棄我的狀態列表)。

我如何獲得Json.Net來適當地反序列化控件及其衍生版本?

看來問題可能是由於$type元數據屬性不是控件的JSON中的第一個屬性這一事實造成的。 通常,Json.Net需要將此屬性設置為第一個才能識別它。 嘗試添加

MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead

反序列化時將其設置為您的設置。 這應該允許Json.Net稍后在JSON中找到$type屬性。

我認為您應該在Web-api啟動類中設置配置。

嘗試在startup.cs文件中輸入類似

        GlobalConfiguration.Configuration.Formatters.Clear(); // or remove just the json one 

        var jsonformatter = new System.Net.Http.Formatting.JsonMediaTypeFormatter()
        {
            SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings()
            {
                // all your configurations
                TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All
            }
        };

        GlobalConfiguration.Configuration.Formatters.Add(jsonformatter);

我認為您正在丟失信息,因為在該方法中獲得了反序列化的Object項(頁面),然后通過調用page.tostring()方法再次對其進行序列化,然后使用序列化程序屬性對其進行反序列化。

暫無
暫無

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

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