当前位置: 首页 > article >正文

.netframework升级为.net8以后元组数据返回格式变成了 [{}]

问题代码

问题描述:MatExpireMoney这个方法前端请求以后得到的返回值是[{}]

public async Task<JsonResult> MatExpireMoney(int platId = 0)
 {
     if (platId == 0)
     {
         platId = NowUser.PlatId;
     }
     var schIds = GetSchIds(platId);
     var expireMatMoney = storageRepo.Where(r => (r.Qty1 > 0 || r.Qty2 > 0) && schIds.Contains(r.SchoolId) && r.ExpirDate < nowDate).Sum(r => (decimal?)(r.Price * (r.Qty1 + r.Qty2))) ?? 0;
     var value = PriceConvert(expireMatMoney);
     return Json(value);
 }
public List<(decimal Money, string Unit)> PriceConvert(decimal? price)
{
    var unit = "";
    if (price > 0)
    {
        if (price > 100000000)
        {
            price = (decimal?)Math.Round((double)(price / 100000000), 2);
            unit = "亿";
        }
        else if (price > 10000)
        {
            price = (decimal?)Math.Round((double)(price / 10000), 2);
            unit = "万";
        }
        else
        {
            price = price;
            unit = "元";
        }

    }
    else
    {
        price = 0;
        unit = "元";
    }
    List<(decimal Money, string Unit)> model = new List<(decimal Money, string Unit)>();
    model.Add(((decimal)price, unit));
    return model;
} 

原因

从 .NET Framework 升级到 .NET 8 后,返回的数据格式变成了 [{}],这通常是因为 .NET Core 及更高版本(包括 .NET 8)对 JSON 序列化的默认行为发生了变化

  1. 默认序列化器变化
    在 .NET Framework 中,默认使用的是 Newtonsoft.Json(即 Json.NET)进行 JSON 序列化。
    在 .NET Core 及更高版本中,默认使用的是 System.Text.Json,它的行为与 Newtonsoft.Json 有所不同。

  2. System.Text.Json 的行为差异
    System.Text.Json 对匿名类型、值类型和集合的序列化行为与 Newtonsoft.Json 不同。
    例如,System.Text.Json 会将 List<(decimal Money, string Unit)> 序列化为 [{}],因为它无法直接处理元组类型的集合。

  3. 返回类型问题
    在 .NET Framework 中,JsonResult 可能对返回值进行了隐式处理,而在 .NET 8 中,JsonResult 的行为更加严格。

解决方案

方案 1:修改返回类型

将 List<(decimal Money, string Unit)> 改为一个明确的类类型,System.Text.Json 可以更好地处理类类型的序列化。

public class MoneyModel
{
    public decimal Money { get; set; }
    public string Unit { get; set; }
}

public List<MoneyModel> PriceConvert(decimal? price)
{
    var unit = "";
    if (price > 0)
    {
        if (price > 100000000)
        {
            price = (decimal?)Math.Round((double)(price / 100000000), 2);
            unit = "亿";
        }
        else if (price > 10000)
        {
            price = (decimal?)Math.Round((double)(price / 10000), 2);
            unit = "万";
        }
        else
        {
            price = price;
            unit = "元";
        }
    }
    else
    {
        price = 0;
        unit = "元";
    }

    return new List<MoneyModel>
    {
        new MoneyModel { Money = (decimal)price, Unit = unit }
    };
}

然后在 MatExpireMoney 方法中直接返回 List:

public async Task<JsonResult> MatExpireMoney(int platId = 0)
{
    if (platId == 0)
    {
        platId = NowUser.PlatId;
    }
    if (platId == 155) // 航空学院 特殊处理
    {
        var path = "/135/screen/new/timeout/r.do";
        var hk_Value = await HK_GetRequest<List<HK_MoneyModel>>(platId, path, "食材过期金额");
        return Json(hk_Value);
    }

    var schIds = GetSchIds(platId);
    var expireMatMoney = storageRepo
        .Where(r => (r.Qty1 > 0 || r.Qty2 > 0) && schIds.Contains(r.SchoolId) && r.ExpirDate < nowDate)
        .Sum(r => (decimal?)(r.Price * (r.Qty1 + r.Qty2))) ?? 0;

    var value = PriceConvert(expireMatMoney);
    return Json(value);
}

方案 2:配置 System.Text.Json 的序列化选项

如果不想修改返回类型,可以通过配置 System.Text.Json 的序列化选项来支持元组类型的序列化。
在 Startup.cs 或 Program.cs 中配置 JSON 选项:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null; // 保持属性名称大小写
        options.JsonSerializerOptions.Converters.Add(new TupleConverter()); // 添加自定义元组转换器
    });

然后实现一个自定义的 JsonConverter 来处理元组类型:

public class TupleConverter : JsonConverter<List<(decimal Money, string Unit)>>
{
    public override List<(decimal Money, string Unit)> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, List<(decimal Money, string Unit)> value, JsonSerializerOptions options)
    {
        writer.WriteStartArray();
        foreach (var item in value)
        {
            writer.WriteStartObject();
            writer.WriteNumber("Money", item.Money);
            writer.WriteString("Unit", item.Unit);
            writer.WriteEndObject();
        }
        writer.WriteEndArray();
    }
}

方案3:方案 3:回退到 Newtonsoft.Json

如果不想修改代码逻辑,可以回退到 Newtonsoft.Json,这是 .NET Framework 中默认的 JSON 序列化库。
安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包:

dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson

在 Startup.cs 或 Program.cs 中配置:

builder.Services.AddControllers()
    .AddNewtonsoftJson(); // 使用 Newtonsoft.Json 作为默认序列化器

总结

推荐方案 1:修改返回类型为明确的类类型,这是最规范和可维护的方式。
方案 2:适合需要保留元组类型的场景,但需要额外实现自定义转换器。
方案 3:适合快速迁移,但长期来看不建议依赖 Newtonsoft.Json。


http://www.kler.cn/a/534776.html

相关文章:

  • 【Linux】24.进程间通信(3)
  • 通过C/C++编程语言实现“数据结构”课程中的链表
  • 基于微信小程序的校园水电费管理平台设计与实现
  • Spring @Lazy:延迟初始化,为应用减负
  • ubuntu 网络管理--wpa_supplicant、udhcpc
  • 【怎么用系列】短视频戒除—1—对推荐算法进行干扰
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_vslprintf 函数
  • 面向对象编程的三大特性
  • LeetCode 1726. Tuple with Same Product
  • vue2-插槽slot
  • 13.PPT:诺贝尔奖【28】
  • Kappa数据架构学习小结
  • 惠普HP工作站如何关闭关闭RAID?
  • DeepSeek 部署过程中的问题
  • 2025年家用音响市场分析:潜力无限,音质为王的新纪元
  • PyTorch 预分配显存是什么,为什么会有PyTorch 预分配显存
  • 【C语言系列】深入理解指针(5)
  • RabbitMQ深度探索:五种消息模式
  • CentOS 7.3编译Rsyslog 8.1903.0
  • 机器学习9-卷积和卷积核2
  • Android_P_Audio_系统(1) — Auido 系统简介
  • 【FPGA】 MIPS 12条整数指令 【3】
  • UE_C++ —— Properties
  • 高手之间的较量,是“想过”和“想透”之间的较量
  • 深入理解小波变换:信号处理的强大工具
  • python代码