我想转换其中包含多个数据表的数据集。
以下是示例,
数据集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工具?
答案 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; }
}