You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON反序列化为DataTable时浮点数被转为整数的问题求解

解决JSON反序列化为DataTable时浮点数被转成整数的问题

我之前也碰到过一模一样的情况!问题出在Json.NET反序列化为DataTable时的自动类型推断逻辑——它会根据JSON数组里第一个元素的字段值来确定整个列的数据类型。你看你的第一条数据里Discount是整数20,所以它直接把Discount列的类型设成了Int32,后面的10.3、15.5就被强制截断成整数了,哪怕你设置了FloatParseHandling.Decimal也没用,因为列类型已经被固定成整数了。

下面给你几个靠谱的解决方案,按推荐程度排序:

方案一:用自定义实体类反序列化(最推荐)

先定义一个和JSON结构匹配的实体类,明确指定所有数值字段为decimal类型,这样反序列化时就不会出现类型推断错误:

public class ImportProduct
{
    public string ProdName { get; set; }
    public decimal Qty { get; set; }
    public decimal Rate { get; set; }
    public decimal Discount { get; set; }
}

然后先把JSON反序列化为List<ImportProduct>,再转换成DataTable:

// 反序列化为实体列表
var productList = JsonConvert.DeserializeObject<List<ImportProduct>>(
    objParam["ImportData"].ToString(),
    new JsonSerializerSettings { FloatParseHandling = FloatParseHandling.Decimal }
);

// 转换为DataTable
DataTable dt = ToDataTable(productList);

这里需要一个通用的List<T>转DataTable的工具方法:

public static DataTable ToDataTable<T>(List<T> items)
{
    DataTable dataTable = new DataTable(typeof(T).Name);
    
    // 获取实体类的所有公共属性
    PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
    
    // 添加列到DataTable
    foreach (PropertyInfo prop in props)
    {
        // 处理可空类型
        Type columnType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
        dataTable.Columns.Add(prop.Name, columnType);
    }
    
    // 填充数据行
    foreach (T item in items)
    {
        object[] values = new object[props.Length];
        for (int i = 0; i < props.Length; i++)
        {
            values[i] = props[i].GetValue(item, null) ?? DBNull.Value;
        }
        dataTable.Rows.Add(values);
    }
    
    return dataTable;
}

这种方法类型安全,扩展性也强,后续字段变更只需要修改实体类就行。

方案二:手动创建DataTable并指定列类型

如果你不想定义实体类,可以先手动创建DataTable并明确指定每一列的类型,再逐行解析JSON数据填充:

// 手动创建DataTable,指定所有数值列为decimal
DataTable dt = new DataTable();
dt.Columns.Add("ProdName", typeof(string));
dt.Columns.Add("Qty", typeof(decimal));
dt.Columns.Add("Rate", typeof(decimal));
dt.Columns.Add("Discount", typeof(decimal));

// 把JSON字符串解析为JArray
JArray importDataArray = JArray.Parse(objParam["ImportData"].ToString());

// 逐行填充数据
foreach (JObject productObj in importDataArray)
{
    DataRow row = dt.NewRow();
    row["ProdName"] = productObj["ProdName"].ToString();
    row["Qty"] = productObj["Qty"].Value<decimal>();
    row["Rate"] = productObj["Rate"].Value<decimal>();
    row["Discount"] = productObj["Discount"].Value<decimal>();
    dt.Rows.Add(row);
}

这种方法直接控制列的类型,完全避免了自动推断的问题,适合临时快速解决问题。

方案三:临时调整JSON数据顺序(不推荐)

如果你只是临时测试,可以把第一条数据的Discount改成带小数的形式(比如20.0),这样Json.NET会推断Discount列为decimal类型。但这种方法依赖数据顺序,一旦后续JSON的第一条数据又变成整数,问题会再次出现,所以不建议在生产环境使用。


内容的提问来源于stack exchange,提问作者mangesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:55:52