从 DataTable 格式化 JSON 对象

Posted

技术标签:

【中文标题】从 DataTable 格式化 JSON 对象【英文标题】:Format JSON Object from DataTable 【发布时间】:2017-09-21 16:28:38 【问题描述】:

我有一个 SQL 存储过程,它返回 2 个动态结果集 - 数据(在 JSON 中名为“表”)和一组列(表 1)。

这是我运行存储过程的 C# 代码...

using (SqlConnection sqlcon = new SqlConnection(ConfigurationManager.ConnectionStrings["TESTCONN"].ConnectionString))

    using (SqlCommand cmd = new SqlCommand("[Model].[TaskRecord_GetAll]", sqlcon))
    
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@Period", period);

        using (SqlDataAdapter da = new SqlDataAdapter(cmd))
        
            DataSet ds = new DataSet();
            DataTable dt1 = new DataTable();
            DataTable dt2 = new DataTable();

            da.Fill(ds);
            dt1 = ds.Tables[0];
            dt2 = ds.Tables[1];

            string json = JsonConvert.SerializeObject(ds, Formatting.Indented);
            return json;
        
    

这是上面代码中我当前的 JSON 对象...


  "Table": [
    
      "Entity": "TEST",
      "Period": "2017-08-31T00:00:00",
      "Level": "5",
      "Errors": "Approved",
      "Process": "OK",
      "Corporate": "Created"
    
  ],
  "Table1": [
    
      "ColumnName": "Entity"
    ,
    
      "ColumnName": "Period"
    ,
    
      "ColumnName": "Level"
    ,
    
      "ColumnName": "Errors"
    ,
    
      "ColumnName": "Process"
    ,
    
      "ColumnName": "Corporate"
    
  ]

但是,我需要这种格式的 JSON 对象:


  "Table": [
    
      "Entity": "TEST",
      "Period": "2017-08-31T00:00:00",
      "Level": "5",
      "Errors": "Approved",
      "Process": "OK",
      "Corporate": "Created"
    
  ],
  "Table1": [
    
      "Entity",
      "Period",
      "Level",
      "Errors",
      "Process",
      "Corporate"
    
  ]

还有我的第二个 SQL 结果集(提供给 Table1)...

我需要在 DataTable 代码中更新什么以确保返回所需的 JSON 对象?我是否必须更改 SQL 存储过程返回数据的方式?

我不能使用 LINQ/EF,因为列是动态的,并且任何数字都可以从存储过程中返回。

【问题讨论】:

你能定义'ColumnName'吗? "ColumnName" 是从存储过程返回的列的名称。不幸的是,它的值是动态的,所以它们可以是任何东西。 如果您不想要“ColumnName”,为什么要从程序中返回它?我错过了什么吗? 【参考方案1】:

您必须转换为如下列表:

public static class DataTableToList

    public static List<T> ToList<T>(this DataTable dataTable)
        where T:class,new()
    
        var list = new List<T>();
        var typeOfT = typeof(T);
        foreach (DataRow row in dataTable.Rows)
        
            var t = new T();
            foreach (DataColumn column in dataTable.Columns)
            
                var propertyName = column.ColumnName;                    
                var property = t.GetType().GetProperty(propertyName);
                if (property != null)
                
                    property.SetValue(t, Convert.ChangeType(row[column],property.PropertyType,null));
                
            
            list.Add(t);
        
        return list;
    

使用:

    public class Table
    
        public string Entity  get; set; 
        public int Period  get; set; 
        public string Level  get; set; 
        public string Process  get; set; 
        public string Corporate  get; set; 
    

var list = dataTable.ToList<Table>();
var jsonString = JsonConvert.SerializeObject(list)

应该可以的。

【讨论】:

应该dataTable.ToList();读取数据表.ToList(); 不,您必须创建一个具有我将更新 anwser 的属性的类 SQL 返回动态结果,因此在运行之前我不会知道列。因此 Table 类将不起作用。
【参考方案2】:

这段代码对我有用。我使用 NewtonSoft JSON 来组合两个 JSON 对象...

using (SqlConnection sqlcon = new SqlConnection(ConfigurationManager.ConnectionStrings["TESTCONN"].ConnectionString))

    using (SqlCommand cmd = new SqlCommand("[Model].[TaskRecord_GetAll]", sqlcon))
    
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@Period", period);

        using (SqlDataAdapter da = new SqlDataAdapter(cmd))
        
            DataSet ds = new DataSet();
            DataTable dt1 = new DataTable();
            DataTable dt2 = new DataTable();

            da.Fill(ds);
            dt1 = ds.Tables[0];
            dt2 = ds.Tables[1];

            List<DataRow> list = dt2.AsEnumerable().ToList();

            List<string> colList = new List<string>();
            foreach(DataRow row in list)
            
                colList.Add(row.ItemArray[0].ToString());
            

            var jsonString = JsonConvert.SerializeObject(new
            
                columns = colList
            , Formatting.Indented);

            ds.Tables.Remove(dt2);

            string json = JsonConvert.SerializeObject(ds, Formatting.Indented);

            JObject o1 = JObject.Parse(jsonString);
            JObject o2 = JObject.Parse(json);

            o1.Merge(o2, new JsonMergeSettings
            
                // union array values together to avoid duplicates
                MergeArrayHandling = MergeArrayHandling.Union
            );
            string jsonResult = o1.ToString();

            return jsonResult;
        
    

【讨论】:

以上是关于从 DataTable 格式化 JSON 对象的主要内容,如果未能解决你的问题,请参考以下文章

jstree做动态树,json格式传输,存储过程获得datatable之类,不知道如何把datatable转换为需要的json数据格式

用 JSON 对象填充 DataTable

C#将datatable生成easyui的绑定tree 的json数据格式

DataTable 转换成 Json的3种方法

C# DataTable转json 时间格式化

为啥 JSON.NET 以这种格式在我的 DataTable 中输出 DateTime 值?