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

时间:2014-02-12 11:49:36

标签: c# json json.net

我想转换其中包含多个数据表的数据集。

以下是示例,

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

Dataset

我想要的结果如下,

{
    "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工具?

3 个答案:

答案 0 :(得分:6)

您可以通过为DataSet实现自定义JsonConverter来获取所需的JSON,如下所示:

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"
    }
  ]
}

答案 1 :(得分:2)

我认为Json.Net不会自动执行此操作,但您应该可以使用Typed Datasets执行此操作。

类型化数据集与常规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传递一行,最后得到一个对象结构。这可以很容易地序列化为您想要的格式。

请注意,必须修改代码供您使用,并且可能无法按原样编译。但这个概念应该是清楚的。

答案 2 :(得分: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; }
}