为什么ValueTuple的return值为空JSON?

Why the return value of ValueTuple is empty JSON?

在 .NET 5 中,我创建了一个默认的 webapi 解决方案“WebApplication1”,并且我在 WeatherForecastController 中有一个操作:

        [HttpGet]
        [Route("[action]")]
        public (bool,string) Test()
        {
            return (true, "have a test!");
        }

为什么我总是得到一个空的 JSON {}

你所做的应该是 Tuple<T1,T2> 的类型。像下面这样更改你的代码:

[HttpGet]
[Route("[action]")]
public Tuple<bool,string> Test()
{
    return new Tuple<bool, string>(true, "have a test!");
}

问题是 ASP.NET 核心使用 System.Text.Json 进行序列化。但它不能处理(命名的)元组:

var result = (Message: "hello", Success: true);
var json = JsonSerializer.Serialize(result);
Console.WriteLine(json);

这会输出一个空对象 {}

Json.NET 可以序列化它,但需要注意:它不保留元组键。

var result = (Message: "hello", Success: true);
var json = JsonConvert.SerializeObject(result);
Console.WriteLine(json);

这输出:

{"Item1":"hello","Item2":true}

因此,如果您想保留密钥,最简单的选择是使用包装器 class:

public class Result<T>
{
    public T Data { get; set; }
    public bool Success { get; set; }
}

[HttpGet]
public async Task<ActionResult<Result<string>>> Hello(CancellationToken cancellationToken)
{
    // ...
    return Ok(new Result<string>{Data = "hello", Success = true});
}

或者您可以选择艰难的方式并编写一个考虑元组键的自定义序列化程序。但即使那样也行不通,因为反射信息不包括密钥。我的猜测是编译器在解析密钥后丢弃了此信息。