使用来自SQLDataReader的数据创建嵌套的JSON

时间:2019-10-17 20:40:40

标签: c# asp.net json json.net

我是.NET的新手,正在尝试实现shape-json在Node世界中的作用。

从shape-json npm页面复制:

给出以下对象数组:

var input = [
  {pid: 1, contributor: 'jdalton', projectID: 1, projectName: 'lodash'},
  {pid: 1, contributor: 'jdalton', projectID: 2, projectName: 'docdown'},
  {pid: 1, contributor: 'jdalton', projectID: 3, projectName: 'lodash-cli'},
  {pid: 2, contributor: 'contra',  projectID: 4, projectName: 'gulp'},
  {pid: 3, contributor: 'phated',  projectID: 4, projectName: 'gulp'},
]

您可以应用这样的模式:

var scheme = {
  "$group[contributors](pid)": {
    "id": "pid",
    "name": "contributor",
    "$group[projects](projectID)": {
      "id": "projectID",
      "name": "projectName"
    }
  }
};

要获得这样的嵌套JSON:

{
  "contributors": [
    {
      "id": 1,
      "name": "jdalton",
      "projects": [
        {
          "id": 1,
          "name": "lodash"
        },
        {
          "id": 2,
          "name": "docdown"
        },
        {
          "id": 3,
          "name": "lodash-cli"
        }
      ]
    },
    {
      "id": 2,
      "name": "contra",
      "projects": [
        {
          "id": 4,
          "name": "gulp"
        }
      ]
    },
    {
      "id": 3,
      "name": "phated",
      "projects": [
        {
          "id": 4,
          "name": "gulp"
        }
      ]
    }
  ]
}

就我而言,我有一个产品层次结构(产品类->产品子类->产品),我试图将其表示为嵌套JSON。

背景:

  • 我正在从MySQL表中获取数据并将其读取到 MySqlDataReader

  • 跟随这个SO question,我已经能够序列化 数据转换成JSON

我不知道如何像上面的示例那样创建嵌套的JSON。请指教。

1 个答案:

答案 0 :(得分:3)

MySqlDataReader实现了IDataReader接口,因此我们可以使用LINQ lambda expression遍历其行并将其转换为适当的.Net数据模型。然后,可以使用将数据模型序列化为JSON。

首先,从this answerJoel Coehoorn抓取以下扩展方法:

public static class DataReaderExtensions
{
    // Adapted from this answer https://stackoverflow.com/a/1202973
    // To https://stackoverflow.com/questions/1202935/convert-rows-from-a-data-reader-into-typed-results
    // By https://stackoverflow.com/users/3043/joel-coehoorn
    public static IEnumerable<T> SelectRows<T>(this IDataReader reader, Func<IDataRecord, T> select)
    {
        while (reader.Read())
        {
            yield return select(reader);
        }
    }
}

然后您可以生成所需的JSON,如下所示:

using (IDataReader reader = cmd.ExecuteReader())
{
    var query = reader
        .SelectRows(r => 
                    new
                    {
                        id = r.GetInt64(r.GetOrdinal("pid")),
                        name = r["contributor"].ToString(),
                        project = new {id = r.GetInt64(r.GetOrdinal("projectID")), name = r["projectName"].ToString() },
                    }
                   )
        .GroupBy(r => new { r.id, r.name })
        .Select(g => new { g.Key.id, g.Key.name, projects = g.Select(i => i.project) });

    var json = JsonConvert.SerializeObject(new { contributors = query }, Formatting.Indented);

    Console.WriteLine(json);
}

注意:

  • 我正在将数据读取器的行转换为由anonymous type对象组成的数据模型,但是如果愿意,可以将显式类型的对象用于最终结果。

  • GroupBy用于按贡献者ID和名称将所有贡献分组。

  • Select用于将可枚举的元素投影为新形式。

  • 这种方法完全跳过了将原始查询结果序列化为JSON,然后解析并重组该初始JSON的中间步骤。

  • query本身是惰性的,因此请确保在处置数据读取器之前对其进行评估。在上面的代码中,Json.NET实际上是在对JsonConvert.SerializeObject的调用内的序列化过程中执行评估的。

  • 我不确定id列是32位整数还是64位整数,因此为了安全起见,我假定较大的列。

  • 该代码假定所有记录值都不是null

演示小提琴here使用DataTableDataTableReader模拟以上内容。