DataMember 属性在 dotnet core 3.0 中不受尊重

DataMember Attribute is not honored in dotnet core 3.0

我创建了一个示例 dotnet core 3.0 Web API 项目并进行了以下更改,

  1. 创建模型class测试数据
using System.Runtime.Serialization;
namespace WebApplication17.Models
{
    [DataContract]
    public class TestData
    {
        [DataMember(Name = "testaction")]
        public string Action { get; set; }
    }
}

然后我在控制器 WeatherForecastController 中进行了更改,以添加一个 post 端点

[HttpPost("package/{packageName}/version/{version}")]
public void Post(string packageName, string version, [FromBody] TestData activityPayload)
{
    Console.WriteLine(activityPayload.Action);
}

现在我用 postman 或 curl with body

打了个电话
{   
    "testaction": "action"  
}

还是在WeatherForecastControllerPost方法中,activityPayload.Actionnull

我原以为是 'action'

[JsonPropertyName("testaction")] 属性添加到 Action 属性。这应该可以解决您的问题。

更多信息请看这里: https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/

Asp.Net Core 3 默认不支持 [DataContract][DataMember],基于此 Github 看来他们不会很快添加它问题

System.Text.Json support to System.Runtime.Serialization

如果您想切换回以前使用 Newtonsoft.Json 的默认设置,它确实尊重这些属性,那么您必须执行以下操作:

  1. 安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet 包。

  2. ConfigureServices()中添加对AddNewtonsoftJson()

    的调用
public void ConfigureServices(IServiceCollection services) {
    //...

    services.AddControllers()
        .AddNewtonsoftJson(); //<--

    //...
}

自 .NET Core 3.0 RC1 起,System.Text.Json 库不支持 System.Runtime.Serialization 属性。您可以在 GitHub 上找到一个跟踪此遗漏的问题,但现在似乎没有任何改变它的意图。

选项 1:Newtonsoft.Json

在此期间你可以做的是切换到使用 Newtonsoft.Json 作为 ASP.NET Core 3.0 的 JSON 序列化程序,它应该恢复此功能(代价是不利用System.Text.Json 解析器,速度要快一些)。

首先,在您的项目中添加对 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包的引用:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
  </ItemGroup>
</Project>

然后在您的服务集合上调用分机。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
            .AddNewtonsoftJson();
}

选项 2:使用 System.Text.Json.Serialization

另一方面,如果您愿意在没有 System.Runtime.Serialization 属性的情况下定义您的模型并改用 System.Text.Json.Serialization 属性,那么您可以执行以下操作:

using System.Text.Json.Serialization;
namespace WebApplication17.Models
{
    public class TestData
    {
        [JsonPropertyName("testaction")]
        public string Action { get; set; }
    }
}

您可以在此处找到支持的属性的完整列表:https://docs.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonpropertynameattribute?view=netcore-3.0

我的两分钱。

以下示例应该有所帮助。

以下是我从 OData Api 得到的响应 json。

{
    "@odata.context": "http://localhost/odata/$metadata#GadgetsOdata(Id,ProductName,Cost,Brand,Type)",
    "@odata.count": 3,
    "value": [
        {
            "Id": 1,
            "ProductName": "Pen Drive",
            "Brand": "Sony",
            "Cost": 600,
            "Type": "Accessories"
        },
        {
            "Id": 2,
            "ProductName": "Head Phone",
            "Brand": "Sony",
            "Cost": 3000,
            "Type": "Computer Accessories"
        },
        {
            "Id": 3,
            "ProductName": "Key board",
            "Brand": "Hp",
            "Cost": 1000,
            "Type": "Computer Accessories"
        }
    ]
}

以下是我用来反序列化的类

public class ExpectedODataGadgetModel
{
    [JsonPropertyName("@odata.count")]
    public int ODataCount { get; set; } = default!;
    [JsonPropertyName("@odata.context")]
    public string ODataContext { get; set; } = default!;

    public List<ExpectedGadgetModel> value { get; set; } = default!;
}
public class ExpectedGadgetModel
{
    public int Id { get; set; }
    public string ProductName { get; set; } = default!;
    public string Brand { get; set; } = default!;
    public decimal Cost { get; set; } = default!;
    public string Type { get; set; } = default!;
}

注意 JsonPropertyName 属性。

最后这就是我对它进行消毒的方法。

var responseStream = await _httpClient.GetStreamAsync(url);
var gadgets = await JsonSerializer.DeserializeAsync<ExpectedODataGadgetModel>(responseStream);

这里的_httpClient是我们在.net core中使用的System.Net.Http.HttpClient对象。

并且 JsonSerializer 来自 System.Text.Json 而不是 NewtonsoftJson。