Convert DataSet with multiple Datatables to Json

余生颓废 提交于 2019-12-09 19:05:19

问题


I want to convert a dataset which has multiple data-tables within it.

Following is the example,

The dataset X has two data tables A and B

I want the result as follows,

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

Currently I am using Newtonsoft.Json. Is it possible with Newtonsoft.Json? If not, is it possible with any other .net Json tools?


回答1:


You can get the JSON you want by implementing a custom JsonConverter for the DataSet like this:

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();
    }
}

Here is a demo:

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);
    }
}

Output:

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



回答2:


I don't think Json.Net will do this automatically, but you should be able to do this using Typed Datasets.

A typed dataset is the same as the regular DataSet/DataTable classes, but they extend them with properties for each column in the tables and with relations.

Edit:

Alternatively you could build a method that converts the DataTable structures into a class model and then use Json.Net to serialize that. The data model would be simple, with only two classes, and the conversion should also be quite simple to implement.

Edit 2:

An example of how to convert the data table into a class structure:

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; }
}

Here you can run ClassA.FromDataRow() and pass it one row from TableA and a list of rows from TableB and end up with an object structure. This can easily be serialized to the format you want.

Please note that the code must be modified for your use and will probably not compile as it is. But the concept should be clear.




回答3:


Final Solution for reference

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; }
}


来源:https://stackoverflow.com/questions/21727144/convert-dataset-with-multiple-datatables-to-json

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!