如何编写LINQ查询,该查询将生成具有以下格式的JSON字符串?

时间:2014-10-03 09:26:05

标签: json linq

我有2个相关的表格,如下所示:

CREATE TABLE [dbo].[tbl_People] (
[People_Id] int NOT NULL IDENTITY(1,1) ,
[ActivityDate] date NULL,
[Colour_Id] int NOT NULL
)

CREATE TABLE [dbo].[tbl_Colours] (
[Colour_Id] int NOT NULL IDENTITY(1,1) ,
[Colour_Name] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
)

我试图找到一个格式如下的JSON字符串:

[
    {
        "Month": "June",
        "Red": 3,
        "Blue": 1,
        "Green": 7
    },
    {
        "Month": "July",
        "Red": 6,
        "Blue": 11,
        "Green": 4
    },
    {
        "Month": "August",
        "Red": 1,
        "Blue": 5,
        "Green": 9
    }

]

目前,我能用LINQ获得的最好成绩如下:

var query = from a in context.tbl_Colours
            join t in context.tbl_People
            on a.Colour_Id equals t.People_Id
            group a by new { a.Colour_Name, t.Colour_Id, t.ActivityDate.Value.Month } into result
            select new
            {

                Month = result.Key.Month,
                Colour = result.Key.Colour_Name,
                Frequency = result.Count()
            };

string jsonData = JsonConvert.SerializeObject(query);

返回:

[
    {
        "Month": 6,
        "Colour": "\r\nRed\r",
        "Frequency": 1
    },
    {
        "Month": 7,
        "Colour": "\r\nGreen\r",
        "Frequency": 1
    },
    {
        "Month": 8,
        "Colour": "\r\nRed\r",
        "Frequency": 1
    }

]

看起来接近所需,但我无法调整代码以产生更接近预期的东西。谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

如果你的颜色是固定的,你可以这样做:

var results = (from t in context.tbl_Peoples
            join a in context.tbl_Colours
                on t.Colour_Id equals a.Colour_Id
            group a by t.ActivityDate.Value.Month
            into result
            select new
            {
                Month = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(result.Key), 
                Blue = result.Count(r => r.Colour_Name.Trim() == "Blue"),
                Green = result.Count(r => r.Colour_Name.Trim() == "Green"),
                Red = result.Count(r => r.Colour_Name.Trim() == "Red"),
            });

string jsonData = JsonConvert.SerializeObject(results);

如果您的颜色没有修复并且您想要构建动态属性名称(例如红色,绿色,蓝色,黄色等),那么可行的方法是使用JArray,JObject和JProperty等JSON.net对象来生成动态属性并构建所需的正确JSON输出。

此代码应生成您期望的JSON:

var results = (from t in context.tbl_Peoples
                join a in context.tbl_Colours
                on t.Colour_Id equals a.Colour_Id
                group a by new { a.Colour_Name, t.Colour_Id, t.ActivityDate.Value.Month } into result
                select new
                {
                    result.Key.Month,
                    Colour = result.Key.Colour_Name.Trim(),
                    Frequency = result.Count()
                }).ToList();

var distinctMonths = results.Select(r => r.Month).Distinct().ToList();
var distinctColors = results.Select(r => r.Colour).Distinct().ToList();

var arr = new JArray();

foreach (var month in distinctMonths)
{
    var monthObject = new JObject
    {
        { "Month", CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month) }
    };

    foreach (var color in distinctColors)
    {
        monthObject.Add(color, 0);
    }

    var colorsData = results.Where(d => d.Month == month).Select(a => new {a.Colour, a.Frequency});

    foreach (var color in colorsData)
    {
        monthObject[color.Colour] = color.Frequency;
    }

    arr.Add(monthObject);
}

string jsonData = arr.ToString();

某些示例数据的输出JSON为:

[
  {
    "Month": "May",
    "Blue": 2,
    "Green": 1,
    "Red": 1
  },
  {
    "Month": "November",
    "Blue": 0,
    "Green": 1,
    "Red": 0
  },
  {
    "Month": "January",
    "Blue": 0,
    "Green": 0,
    "Red": 2
  }
]

确保包含一些错误处理来处理边缘情况。