2016-02-24 2 views
0

Класс:Преобразование DataTable в JSON на основе определенных правил

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 недвижимости будет присвоена stack собственности в объекте JSon.
  2. Category Недвижимость будет принадлежать объекту name в объекте json.
  3. Число Category не фиксировано.
  4. Данные Category могут быть представлены или могут отсутствовать в течение данного месяца.
  5. Объект data будет размещен в объекте json для каждого месяца.
  6. Если категория отсутствует в течение месяца, мы должны считать значение нулевым.

Я действительно не уверен, как решить эту проблему. Как я могу приступить к решению этой проблемы. У меня с трудом фиксируется это.

+0

Должно ли это быть DataTable? Может у вас есть IDataReader? –

+0

@MattClark. Да, я могу использовать DataReader. Первоначально я думал, что буду использовать LINQ поверх DataTable, и было бы легко запросить datatable – OpenStack

ответ

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 , и т. д.

+0

Я получаю сообщение об ошибке «Нельзя использовать выражение лямбда как аргумент для динамически отправленной операции без первого его литья в делегат или дерево выражений типа. – OpenStack

+0

@OpenStack dbOutput - это коллекция Dtos здесь, вам нужно отбросить их в объекты для работы этого решения ... Я не знаю как вы вытаскиваете данные из своей базы данных, так что я больше всего могу помочь на этом этапе. – konkked

+0

Благодарим за быстрый ответ. Я вижу, что вы сейчас говорите. в массиве данных, который вы создаете, если значение для какого-либо месяца отсутствует, в настоящее время мы его не показываем. Есть ли способ узнать, нет ли значения в течение месяца, покажите его как null. – OpenStack

0

Вот код, я использую, чтобы преобразовать 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; 
    } 
+0

Я не уверен, что если я последую за тем, что вы делаете, мне нужно преобразовать данные (хранящиеся в datatable или custom object) в JSON . Мне также нужно помнить о правилах, о которых я упомянул. Я просто не вижу способа, которым этот код может помочь мне – OpenStack

+0

@openstack Вы можете отредактировать это, чтобы применить свои правила до создания класса, а затем сериализовать свои объекты в json –