【问题标题】:Converting datatable into JSON based on certain rules根据一定的规则将数据表转换为 JSON
【发布时间】:2016-06-07 06:04:33
【问题描述】:

类:

public class DataCls
    {
        public int Year { get; set; }
        public string Month { get; set; }
        public int MonthOrder { get; set; }
        public string category { get; set; }
        public int Val { get; set; }
    }

数据:

List<DataCls> dlist = new List<DataCls>();
            DataCls dat = new DataCls();
            dat.Year = 2015;
            dat.Month = "Jan";
            dat.MonthOrder = 1;
            dat.category = "A";
            dat.Val = 1;
            dlist.Add(dat);

            dat = new DataCls();
            dat.Year = 2015;
            dat.Month = "Jan";
            dat.MonthOrder = 1;
            dat.category = "B";
            dat.Val = 2;
            dlist.Add(dat);


            dat = new DataCls();
            dat.Year = 2015;
            dat.Month = "Jan";
            dat.MonthOrder = 1;
            dat.category = "C";
            dat.Val = 3;
            dlist.Add(dat);


            dat = new DataCls();
            dat.Year = 2015;
            dat.Month = "Feb";
            dat.MonthOrder = 2;
            dat.category = "A";
            dat.Val = 5;
            dlist.Add(dat);

            dat = new DataCls();
            dat.Year = 2015;
            dat.Month = "Feb";
            dat.MonthOrder = 2;
            dat.category = "B";
            dat.Val = 6;
            dlist.Add(dat);


            dat.Year = 2016;
            dat.Month = "Jan";
            dat.MonthOrder = 1;
            dat.category = "A";
            dat.Val = 4;
            dlist.Add(dat);

            dat = new DataCls();
            dat.Year = 2016;
            dat.Month = "Feb";
            dat.MonthOrder = 2;
            dat.category = "A";
            dat.Val = 7;
            dlist.Add(dat);

            dat = new DataCls();
            dat.Year = 2016;
            dat.Month = "Feb";
            dat.MonthOrder = 2;
            dat.category = "B";
            dat.Val = 8;
            dlist.Add(dat);

            dat = new DataCls();
            dat.Year = 2016;
            dat.Month = "Feb";
            dat.MonthOrder = 2;
            dat.category = "C";
            dat.Val = 9;
            dlist.Add(dat);

            dat = new DataCls();
            dat.Year = 2015;
            dat.Month = "Mar";
            dat.MonthOrder = 3;
            dat.category = "A";
            dat.Val = 10;
            dlist.Add(dat);

我期待的输出。

{
    "Series": [{
        "name": "A",
        "stack": 2015,
        "data": [1, 5, 10]
    }, {
        "name": "B",
        "stack": 2015,
        "data": [2, 6, null]
    }, {
        "name": "C",
        "stack": 2015,
        "data": [3, null, null]
    }, {
        "name": "A",
        "stack": 2016,
        "data": [4, 7, null]
    }, {
        "name": "B",
        "stack": 2016,
        "data": [null,8, null]
    }, {
        "name": "C",
        "stack": 2016,
        "data": [null,9, null]
    }]
}

要记住的要点:

  1. Year 属性将分配给 json 对象中的 stack 属性。
  2. Category 属性将分配给 json 对象中的 name 属性。
  3. Category 的数量不固定。
  4. 给定的Category 在给定的月份可能存在也可能不存在。
  5. val 属性将分配给每个月的 json 对象中的 data 数组。
  6. 如果类别缺失一个月,我们需要将该值视为null。

我真的不知道如何解决这个问题。我该如何着手解决这个问题。我很难解决这个问题。

【问题讨论】:

  • 必须是DataTable吗?你能用 IDataReader 代替吗?
  • @MattClark。是的,我也可以使用 DataReader。我最初以为我会在 DataTable 之上使用 LINQ 并且查询数据表会很容易

标签: c# .net linq c#-4.0 datatable


【解决方案1】:

您可以结合使用 linq 来转换数据,然后使用 Json.NET 创建 json。

  //here assuming monthMap is an int map
  // "Jan" => 1
  // "Feb" => 2
  // etc
  var lqOutput 
           = dbOutput
                .OrderBy(a=>monthMap[a.Month])
                .GroupBy(a=>new{a.Category,a.Year})
                .Select(a=>new{ 
                            name=a.Key.Category,
                            stack=a.Key.Year,
                            data = a.Select(b=>b.Val).ToArray()
                 });

    var json = JsonConvert.SerializeObject(new{ Series = lqOutput});

如果您想跳过未显示的月份,您可以创建一个较小的辅助方法

var dictToArr = new Func<int,Dictionary<int,object>, object[]>((size,d)=>{
        var retv = new object[size];
        foreach(var key in d.Keys)
        {
            if(key>=0)
            {
                retv[key] = d[key];
            }
        }
        return retv;
    });

var lqOutput 
        = dbOutput
                .OrderBy(a=>monthMap[a.Month])
                .GroupBy(a=>new{a.Category,a.Year})
                          .Select(a=>new{ 
                                      name=a.Key.Category,
                                      stack=a.Key.Year,
                                      data = dictToArr ( 12,
                                                a.Select(b=>new{ 
                                                            val= b.Val, 
                                                            idx=monthMap[b.Month]
                                                  }).ToDictionary(
                                                              b=>b.idx,
                                                              b=>b.val as object
                                                  ) )
                                  });

var json = JsonConvert.SerializeObject(new{ Series = lqOutput});

如果你这样做,你需要将一月映射到 0,二月映射到 1,等等

【讨论】:

  • 我说Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type时出错
  • @OpenStack dbOutput 是这里的 Dtos 集合,您需要将它们转换为对象才能使该解决方案起作用...我不知道您是如何将数据从数据库中提取出来的,所以这个是我目前能提供的最大帮助
  • 感谢您的快速回复。我明白你现在在说什么。在您正在创建的数据数组中,如果不存在任何月份的值,目前我们不显示它。有没有办法判断一个值是否在一个月内不存在,将其显示为 null。
  • 感谢您的帮助。我收到An item with the same key has already been added. 错误。看起来像在字典中添加了重复值,但我无法弄清楚我需要进行哪些更改才能使其正常工作
  • 也就是说你一年有两次同月?不确定您想如何处理?
【解决方案2】:

这是我用来将 IDataReader 转换为类的一些代码

public static List<T> DataReaderMapToList<T>(this IDataReader dr)
    {
        var list = new List<T>();
        var obj = default(T);

        var columns = dr.GetSchemaTable().Rows;
        var columnsArray = new DataRow[columns.Count];
        columns.CopyTo(columnsArray, 0);

        var columnNames = columnsArray.Select(x => x[0].ToString());
        while (dr.Read())
        {
            obj = Activator.CreateInstance<T>();

            var type = obj.GetType();
            foreach (var column in columnNames)
            {
                var field = type.GetField(column);
                if (field != null && dr[column].GetType().FullName == field.FieldType.FullName)
                {
                    field.SetValue(obj, dr[column], BindingFlags.SetField, null, null);
                    continue;
                }

                var property = type.GetProperty(column);
                if (property != null && dr[column].GetType().FullName == property.PropertyType.FullName)
                {
                    property.SetValue(obj, dr[column]);
                }
            }

            list.Add(obj);
        }
        return list;
    }

【讨论】:

  • 我不确定我是否遵循您在做什么,我需要将数据(存储在数据表或自定义对象中)转换为 JSON。我还需要记住我提到的规则。我只是看不出这段代码可以帮助我
  • @openstack 您可以在创建类之前对其进行编辑以应用您的规则,然后将您的对象序列化为 json
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 2012-08-12
  • 1970-01-01
  • 2016-04-27
  • 1970-01-01
  • 2019-02-26
相关资源
最近更新 更多