【问题标题】:Deserialization of reference types without parameterless constructor is not supported不支持没有无参数构造函数的引用类型的反序列化
【发布时间】:2019-12-05 15:31:19
【问题描述】:

我有这个 API

 public ActionResult AddDocument([FromBody]AddDocumentRequestModel documentRequestModel)
        {
            AddDocumentStatus documentState = _documentService.AddDocument(documentRequestModel, DocumentType.OutgoingPosShipment);
            if (documentState.IsSuccess)
                return Ok();

            return BadRequest();
        }

这是我的请求模型

    public class AddDocumentRequestModel
    {
        public AddDocumentRequestModel(int partnerId, List<ProductRequestModel> products)
        {
            PartnerId = partnerId;
            Products = products;
        }

        [Range(1, int.MaxValue, ErrorMessage = "Value for {0} must be between {1} and {2}.")]
        public int PartnerId { get; private set; }

        [Required, MustHaveOneElement(ErrorMessage = "At least one product is required")]
        public List<ProductRequestModel> Products { get; private set; }
    }

所以当我试图用这个 body 访问 API 时

{
        "partnerId": 101,
        "products": [{
            "productId": 100,
            "unitOfMeasureId": 102,
            "quantity":5
        }
     ]
}

这是请求:System.NotSupportedException:不支持没有无参数构造函数的引用类型的反序列化。输入“Alati.Commerce.Sync.Api.Controllers.AddDocumentRequestModel”

我不需要无参构造函数,因为它不读取body参数。有没有其他反序列化的方法?

【问题讨论】:

标签: serialization json-deserialization .net-core-3.0


【解决方案1】:

你可以达到你想要的结果。您需要切换到 NewtonsoftJson 序列化(来自包 Microsoft.AspNetCore.Mvc.NewtonsoftJson)

在 Startup.cs 的 ConfigureServices 方法中调用它:

services.AddControllers().AddNewtonsoftJson();

在此之后,你的构造函数将被反序列化调用。

额外信息:我使用的是 ASP Net Core 3.1

稍后编辑:我想提供更多关于此的信息,因为这似乎也可以通过使用 System.Text.Json 来实现,尽管自定义实现是必要的。 jawa 的回答指出,Deserializing to immutable classes and structs 可以通过 System.Text.Json 实现,方法是创建一个自定义转换器(从 JsonConverter 继承)并将其注册到转换器集合(JsonSerializerOptions.Converters),如下所示:

public class ImmutablePointConverter : JsonConverter<ImmutablePoint>
{
...
}

然后……

var serializeOptions = new JsonSerializerOptions();
serializeOptions.Converters.Add(new ImmutablePointConverter());
serializeOptions.WriteIndented = true;

【讨论】:

  • 只需确保为您正在使用的 .Net 或 .Net Core 框架安装正确版本的 Microsoft.AspNetCore.Mvc.NewtonsoftJson。尝试为 .Net Core 3.1 安装 5.x 版本不起作用,但安装 3.1.x 版本可以。 {facepalm}
  • 在 .NET 6 中,在处理字典键中的 System.Uri 时,我们仍然需要使用此解决方案。 docs.microsoft.com/en-us/dotnet/standard/serialization/…
【解决方案2】:

使用 System.Text.Json 仍有一些限制 - 看看这里:https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#table-of-differences-between-newtonsoftjson-and-systemtextjson 尚不支持使用参数化构造函数的无参数构造函数的反序列化(但在他们的计划中)。您可以实现您的自定义 JsonConverter(如本例中:https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#deserialize-to-immutable-classes-and-structs)或 - 如上面建议的 Adrian Nasul:使用 Newtonsoft.Json,然后您可以使用 [JsonConstructor] 属性

【讨论】:

    【解决方案3】:

    以防万一有人遇到与我相同的问题,我使用的是 abstract 类,一旦删除了 abstract 关键字,一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-16
      • 2013-02-19
      • 2016-06-08
      • 2019-10-07
      • 2012-03-12
      • 2021-01-11
      • 2014-10-28
      • 2014-06-30
      相关资源
      最近更新 更多