为什么ReadFromJsonAsync()方法返回具有空值的对象属性?

16
我有一个Blazor WebAssembly应用程序(ASP.Net Core托管,渐进式Web应用程序),具有以下逻辑:
客户端:
protected override async Task OnInitializedAsync() {
    string token = await _loginService.GetToken();

    _http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

    var result = await _http.PostAsJsonAsync("api/api/getcalllogs", userCallsRequestFilters);

    if (result.IsSuccessStatusCode) {
        var morUserCallLogs = await result.Content.ReadFromJsonAsync < MorUserCallLogsResponse > ();

        await js.InvokeAsync < object > ("TestDataTablesAdd", "#example");
    } else {
        morUserCallLogs = new MorUserCallLogsResponse();
    }
}

服务器:(我有以下代码,可以按预期工作的服务器端API:)
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class MorApiController : ControllerBase
...

[HttpPost("getcalllogs")]
public async Task<MorUserCallLogsResponse> GetCallLogs ([FromBody] MorUserCallsRequestFilters filters)
{
...
return result;

服务器端控制器API成功填充了模型,当我进行检查时,我看到以下快照(*某些值已经被屏蔽以确保安全) enter image description here 模型:(我的MorUserCallLogsResponse模型如下所示:)
namespace MyNumberV2.Model
{
    public class MorUserCallLogsResponse
    {
        public MorUserCallLogsResponse()
        { 
            Calls = new List<MorCall>();
        }
        public string Error { get; set; }
        public bool IsSuccessfull { get; set; }
        public string userid;
        public string username;
        ...
        ...
        public List<MorCall> Calls { get; set; }
        public class MorCall
        {
            public string calldate2;
            public string timezone;
            ...
            ...
        }
    }
}

回到 Blazor,当我尝试在下一行读取返回的对象时:
var morUserCallLogs = await result.Content.ReadFromJsonAsync<MorUserCallLogsResponse>();

我的检索到的模型长这样: 在此输入图像描述

正如您所见,我的检索到的模型包含了所有属性和140个嵌套调用对象模型,但是所有属性都是NULL...


2
经典的JSON驼峰式大小写/帕斯卡命名法序列化/反序列化问题 - agua from mars
@aguafrommars 兄弟,非常感谢,我必须为 JSON 创建不区分大小写的选项,并将其传递给 ReadFromJsonAsync 方法。 var options = new JsonSerializerOptions() { Converters = { new JsonStringEnumConverter() }, PropertyNameCaseInsensitive = true }; 我还根据我的需要添加了枚举转换器。 - bzmind
使用JsonSerializerDefaults.Web作为起点可能更好:var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); options.Converters.Add(new JsonStringEnumConverter()); - Michael Csikos
4个回答

15

我忘记为我的所有模型属性添加get; set;了...

{ get; set; }

  public string Error { get; set; }
  public bool IsSuccessfull { get; set; }
  public string userid { get; set; }
  public string username { get; set; }
  .....

2
好的,字段不会序列化,属性会。 - H H
1
在VS中有一个用于创建自动属性的代码片段。输入prop并按两次Tab键即可。我经常使用它来创建新属性。 - Zsolt Bendes
2
另外,设置器必须是公共的。这也是我仍然使用Newtonsoft的原因之一。 - Peter Morris
我的属性是使用 { get; set; } 公开的,但我的对象仍然以默认值结束,所以这并没有解决我的问题。 - Bleak Morn

7

我必须使用以下属性注解:using System.Text.Json.Serialization

 [JsonPropertyName("access_token")]
 public string AccessToken { get; set; }

没错,这应该是被接受的答案,谢谢。 - undefined

2

通过向ReadFromJsonAsync方法传递一个选项参数,我的问题得到了解决,这将使json对于json中的属性是大小写不敏感的,所以在您的情况下,代码应该如下所示:

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};
var result = await result.Content.ReadFromJsonAsync<MorUserCallLogsResponse>(options);

2
"api/api/getcalllogs"与[Route("api/[controller]")][HttpPost("getcalllogs")]不匹配。
根据我的理解,URL应该是"api/MorApi/getcalllogs"
但是再次强调,这将会产生一个404或400错误。

这确实是由于错误在 StackOverflow 上更改了,但实际代码如下: var result = await _http.PostAsJsonAsync("api/morapi/getcalllogs", userCallsRequestFilters); - Zach Ioannou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接