无法使用 .NET 5 中的 JsonSubTypes 反序列化 WebApi 中的 Json,尽管能够在控制台应用程序中

Posted

技术标签:

【中文标题】无法使用 .NET 5 中的 JsonSubTypes 反序列化 WebApi 中的 Json,尽管能够在控制台应用程序中【英文标题】:Unable to Deserialize Json in WebApi with JsonSubTypes in .NET 5, although able to in Console App 【发布时间】:2021-05-10 23:40:33 【问题描述】:

我正在尝试在我的项目的 web api 中实现多态反序列化。我有以下基类和派生类。

基类

    [JsonConverter(typeof(JsonSubtypes), "PointType")]
    public abstract class BasePointRule
    
       public abstract string PointType  get; 
    

派生类

    public class DayOfWeekPointRule : BasePointRule

    public int Id  get; set; 
    public decimal Mon  get; set;  = 0;
    public decimal Tue  get; set;  = 0;
    public decimal Wed  get; set;  = 0;
    public decimal Thu  get; set;  = 0;
    public decimal Fri  get; set;  = 0;
    public decimal Sat  get; set;  = 0;
    public decimal Sun  get; set;  = 0;
    public int GroupId  get; set; 
    public Group Group  get; set; 
    public override string PointType  get; = "DayOfWeekPointRule";


    public DayOfWeekPointRule()
    
    

将子类型的 json 发布到我的 Web Api 控制器时出现错误。这是带有双引号的json转义:


    "PointType":"DayOfWeekPointRule",
    "Mon":0,
    "Tue":0,
    "Wed":0,
    "Thu":0,
    "Fri":0,
    "Sat":0,
    "Sun":0

这里是 web api 控制器方法:

        [HttpPost("AddPointRule")]
    public IActionResult AddPointRule(BasePointRule rule)
    

        ConfigurationService.AddPointRule(rule);
        return Ok();
    

我得到的错误信息是:

System.InvalidOperationException:无法创建“RosterCharm.Models.Rules.BasePointRule”类型的实例。模型绑定的复杂类型不能是抽象类型或值类型,并且必须具有无参数构造函数。记录类型必须有一个主构造函数。或者,给“规则”参数一个非空的默认值。 在 Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder.CreateModel(ModelBindingContext bindingContext) 在 Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext,Int32 propertyData) 在 Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext,IModelBinder modelBinder,IValueProvider valueProvider,ParameterDescriptor 参数,ModelMetadata 元数据,对象值,对象容器) 在 Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.c__DisplayClass0_0.d.MoveNext() --- 上一个位置的堆栈跟踪结束 ---

如果我将控制器路由中的参数从基类更改为派生类,则 json 被正确反序列化。

如果我在控制台应用程序中实现上述内容并调用以下内容,那么 json 也会被反序列化为派生类型,而不会出现问题:

var derivedType = JsonConvert.DeserializeObject<BasePointRule>(json);

这让我认为这个问题是 .Net 特有的(我使用的是 .Net 5),并尝试确保我使用的是 Json.NET(我认为是 Newtonsoft.Json)而不是 System.Text.Json通过在我的 startup.cs 中调用以下内容

services.AddControllers().AddNewtonsoftJson();

任何提示将不胜感激。我正在考虑尝试实现我自己的 Json 转换器,但希望能够轻松利用 json 子类型库。

【问题讨论】:

【参考方案1】:

public IActionResult AddPointRule([FromBody]BasePointRule 规则)

【讨论】:

虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。 这是解决方案的一部分,谢谢。我还必须在客户端更改 axios post 语法,这不是最初问题的一部分。

以上是关于无法使用 .NET 5 中的 JsonSubTypes 反序列化 WebApi 中的 Json,尽管能够在控制台应用程序中的主要内容,如果未能解决你的问题,请参考以下文章

vb.net 4.5 中的 Zipfile “目录名无效。”错误 - 无法确定原因?

.Net 5:无法启动 Ocelot,不受支持的身份验证提供程序

如何从我的 ASP.NET Core 5 Web 应用程序中的 SignalR 操作中解决错误“无法访问已释放的上下文实例”?

.net 3.5 中的反序列化对象

无法从 ASP.Net 网站项目中的代码访问 App_Code 中的类

无法安装 .NET Framework 3.5