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

如何根据自定义Schema反序列化JSON到DataSet并修改列数据类型

解决方案

核心问题说明

你原有实现的错误在于:.NET 中 DataColumn.DataType 属性不支持在 DataTable 已填充数据的场景下直接修改,直接赋值会抛出 ArgumentException 异常。你需要调整实现逻辑,先按照自定义Schema构建符合类型要求的空表结构,再对原始数据做类型转换后填充。

完整实现代码

using Newtonsoft.Json;
using System;
using System.Data;
using System.Collections.Generic;

static void JsonToDataSet(ref DataSet pDs, string json, string schema)
{
    // 1. 反序列化原始JSON得到源数据
    DataSet originalDs = JsonConvert.DeserializeObject<DataSet>(json);
    DataTable originalTable = originalDs.Tables[0];

    // 2. 解析自定义Schema配置
    var schemaObj = JsonConvert.DeserializeObject<SchemaRoot>(schema);
    
    // 3. 新建符合Schema类型要求的空表
    DataTable targetTable = new DataTable(originalTable.TableName);
    foreach (var fieldConfig in schemaObj.schema)
    {
        Type colType = GetColumnType(fieldConfig.type);
        targetTable.Columns.Add(fieldConfig.field, colType);
    }

    // 4. 遍历原始数据,做类型转换后写入新表
    foreach (DataRow originalRow in originalTable.Rows)
    {
        DataRow newRow = targetTable.NewRow();
        foreach (var fieldConfig in schemaObj.schema)
        {
            string fieldName = fieldConfig.field;
            object originalValue = originalRow[fieldName];
            newRow[fieldName] = ConvertValue(originalValue, fieldConfig.type);
        }
        targetTable.Rows.Add(newRow);
    }

    // 5. 赋值给返回的DataSet
    pDs = new DataSet();
    pDs.Tables.Add(targetTable);
}

// 类型映射:自定义Schema的类型对应.NET类型
private static Type GetColumnType(string schemaType)
{
    return schemaType switch
    {
        "int" => typeof(int),
        "date" => typeof(DateTime),
        "bool" => typeof(bool),
        "string" => typeof(string),
        _ => typeof(string) // 未知类型默认用string
    };
}

// 数值转换:处理各类原始值到目标类型的转换
private static object ConvertValue(object originalValue, string targetType)
{
    if (originalValue == DBNull.Value || originalValue == null)
        return DBNull.Value;

    string valueStr = originalValue.ToString().Trim();
    if (string.IsNullOrEmpty(valueStr))
        return DBNull.Value;

    try
    {
        return targetType switch
        {
            "int" => int.Parse(valueStr),
            "date" => DateTime.Parse(valueStr),
            "bool" => ConvertToBool(valueStr),
            _ => valueStr
        };
    }
    catch
    {
        // 转换失败返回空,可根据业务需求调整为默认值
        return DBNull.Value;
    }
}

// 处理各类布尔值格式的转换:支持0/1、"0"/"1"、"Sim"/"Não"等场景
private static bool ConvertToBool(string valueStr)
{
    if (bool.TryParse(valueStr, out bool boolVal))
        return boolVal;
    
    if (int.TryParse(valueStr, out int intVal))
        return intVal != 0;

    // 适配示例中的葡萄牙语是/否值
    return valueStr.Equals("Sim", StringComparison.OrdinalIgnoreCase);
}

// 自定义Schema的序列化辅助类
public class SchemaField
{
    public string field { get; set; }
    public string type { get; set; }
}

public class SchemaRoot
{
    public List<SchemaField> schema { get; set; }
}

注意事项

  • 代码已经适配了你示例中的特殊布尔值场景:数字0/1、字符串"0"/"1"、葡萄牙语的"Sim"/"Não"都可以正确转换为布尔类型
  • 如果有其他特殊的格式转换需求,可以直接修改ConvertValue和ConvertToBool方法的逻辑
  • 转换失败时默认返回DBNull,你可以根据自己的业务需求调整为抛出异常或者设置默认值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 05:39:03