将含有多个数据表的DataSet转换为Json

3

我想将一个包含多个数据表的数据集转换成另一种格式。

以下是一个例子,

数据集X有两个数据表A和B

数据集

我希望得到以下结果,

{
    "type":"A",
    "value":"100",
    "details":[
        {"name":"John", "age":"45", "gender":"M"},
        {"name":"Sebastin", "age":"34", "gender":"M"},
        {"name":"Marc", "age":"23", "gender":"M"},
        {"name":"Natalia", "age":"34", "gender":"F"}
        ]
}

目前我正在使用Newtonsoft.Json。是否可以使用Newtonsoft.Json来实现? 如果不行,是否可以使用其他的.Net Json工具?


datatable A 的数据集.Tables[0] 怎么样?datatable B 的数据集.Tables[1] 呢? - Mahmoude Elghandour
4个回答

6
你可以通过为 DataSet 实现自定义的 JsonConverter 获取所需的 JSON,方法如下:JsonConverter
class CustomDataSetConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(DataSet));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        DataSet x = (DataSet)value;
        JObject jObject = new JObject();
        DataTable a = x.Tables["A"];
        foreach (DataColumn col in a.Columns)
        {
            jObject.Add(col.Caption.ToLower(), a.Rows[0][col].ToString());
        }
        JArray jArray = new JArray();
        DataTable b = x.Tables["B"];
        foreach (DataRow row in b.Rows)
        {
            JObject jo = new JObject();
            foreach (DataColumn col in b.Columns)
            {
                jo.Add(col.Caption.ToLower(), row[col].ToString());
            }
            jArray.Add(jo);
        }
        jObject.Add("details", jArray);
        jObject.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

这里有一个演示:

class Program
{
    static void Main(string[] args)
    {
        DataSet x = new DataSet();
        DataTable a = x.Tables.Add("A");
        a.Columns.Add("Type");
        a.Columns.Add("Value");
        a.Rows.Add("A", "100");
        DataTable b = x.Tables.Add("B");
        b.Columns.Add("Name");
        b.Columns.Add("Age");
        b.Columns.Add("Gender");
        b.Rows.Add("John", "45", "M");
        b.Rows.Add("Sebastian", "34", "M");
        b.Rows.Add("Marc", "23", "M");
        b.Rows.Add("Natalia", "34", "F");

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.Converters.Add(new CustomDataSetConverter());
        settings.Formatting = Formatting.Indented;

        string json = JsonConvert.SerializeObject(x, settings);
        Console.WriteLine(json);
    }
}

输出:

{
  "type": "A",
  "value": "100",
  "details": [
    {
      "name": "John",
      "age": "45",
      "gender": "M"
    },
    {
      "name": "Sebastian",
      "age": "34",
      "gender": "M"
    },
    {
      "name": "Marc",
      "age": "23",
      "gender": "M"
    },
    {
      "name": "Natalia",
      "age": "34",
      "gender": "F"
    }
  ]
}

Brian,非常感谢你的解决方案。今天我遇到了类似的问题,这个方案非常有效。 - Ken Palmer

2
我认为Json.Net不会自动完成这项任务,但是您可以使用类型化数据集来实现。类型化数据集与常规的DataSet/DataTable类相同,但它们通过为表中的每一列和关系添加属性来扩展它们。
编辑:
或者,您可以构建一个将DataTable结构转换为类模型的方法,然后使用Json.Net对其进行序列化。数据模型将是简单的,仅有两个类,并且转换也应该很容易实现。
编辑2:
将数据表转换为类结构的示例:
public class ClassA
{
    public string Type { get; set; }
    public int Value { get; set; }
    public List<ClassB> Details { get; set; }

    public static ClassA FromDataRow(DataRow row, IEnumerable<DataRow> relatedRows)
    {
        var classA = new ClassA
            {
                Type = (string) row["Type"],
                Value = (int) row["Value"],
                Details = relatedRows.Select(r => new ClassB
                    {
                        Name = (string)r["Name"],
                        Age = (int)r["Age"],
                        Gender = (string)r["Gender"]
                    }).ToList()
            };

        return classA;
    }
}

public class ClassB
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
}

您可以运行ClassA.FromDataRow(),将来自TableA的一行和来自TableB的行列表传递给它,并最终得到一个对象结构。这很容易序列化为所需格式。

请注意,代码必须根据您的使用进行修改,因此可能无法直接编译。但是概念应该很清晰。


请问您能否提供一个链接,其中使用了嵌套JSON数据的“将DataTable结构转换为类模型”的教程? - Vyas Rao
不是很确定,但我可以尝试举个例子 :-) - Rune Grimstad

1

参考最终解决方案

using System.Web.Script.Serialization;
public class ClassA
{
    public string Type { get; set; }
    public string Value { get; set; }
    public List<ClassB> Details { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {

        DataSet x = new DataSet();
        DataTable a = x.Tables.Add("A");
        a.Columns.Add("Type");
        a.Columns.Add("Value");
        a.Rows.Add("A", "100");
        DataTable b = x.Tables.Add("B");
        b.Columns.Add("Name");
        b.Columns.Add("Age");
        b.Columns.Add("Gender");
        b.Rows.Add("John", "45", "M");
        b.Rows.Add("Sebastian", "34", "M");
        b.Rows.Add("Marc", "23", "M");
        b.Rows.Add("Natalia", "34", "F");

        var s = FromDataRow(a.Rows[0], b.AsEnumerable());
        JavaScriptSerializer jss = new JavaScriptSerializer();

        string output = jss.Serialize(s);
    }

    public static ClassA FromDataRow(DataRow row, IEnumerable<DataRow> relatedRows)
    {
        var classA = new ClassA
        {
            Type = (string)row["Type"],
            Value = (string)row["Value"],
            Details = relatedRows.Select(r => new ClassB
            {
                Name = (string)r["Name"],
                Age = (string)r["Age"],
                Gender = (string)r["Gender"]
            }).ToList()
        };

        return classA;
    }
}

public class ClassB
{
    public string Name { get; set; }
    public string Age { get; set; }
    public string Gender { get; set; }
}

0
这是一个简化的答案:
var datasetList = new List();
var yourChanges = yourDataset.GetChanges();

datasetList.Add(yourChanges);

一旦修改完成:

JsonConert.Serialize(datasetList, Formatting.Indented);

这将为所有记录生成JSON。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接