我正在尝试使用Newtonsoft JsonConverter序列化C#数据表
法典:
JsonConvert.SerializeObject(dt); //dt is DataTable
我得到的结果是:
[
{
"Name": "Tiger Nixon",
"Position": "System Architect",
"Address": "Edinburgh",
"No": "5421"
},
{
"Name": "Garrett Winters",
"Position": "Accountant",
"Address": "Tokyo",
"No": "8422"
}
]
我想要的结果是:
{
"data": [
[
"Tiger Nixon",
"System Architect",
"Edinburgh",
"5421"
],
[
"Garrett Winters",
"Accountant",
"Tokyo",
"8422"
]
]
}
是否可以使用牛顿软件自定义输出?我尝试编写自己的代码来通过在DataTable
上使用foreach
来序列化DataTable,但与Newtonsoft相比,性能是白天和黑夜。
任何帮助将不胜感激
以下JsonConverter
来做到这一点:
public class DataTableTo2dArrayConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(DataTable).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var table = (DataTable)value;
var array2d = table.AsEnumerable().Select(row => table.Columns.Cast<DataColumn>().Select(col => row[col]));
serializer.Serialize(writer, new { data = array2d });
}
}
然后像这样使用它:
var settings = new JsonSerializerSettings();
settings.Converters.Add(new DataTableTo2dArrayConverter());
var json = JsonConvert.SerializeObject(dt, Formatting.Indented, settings);
请注意,我对System.Data.DataTableExtensions.AsEnumerable()
的使用需要引用 System.Data.DataSetExtensions.dll
。
这是我在阅读JasonWilczak提供的链接后的做法
public class JqueryDatatablesConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(DataTable).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
dynamic dt = (DataTable)value;
dynamic count = dt.Columns.Count - 1;
writer.WriteStartObject();
writer.WritePropertyName("data");
writer.WriteStartArray();
foreach (DataRow dr in dt.Rows) {
writer.WriteStartArray();
for (int x = 0; x <= count; x++) {
serializer.Serialize(writer, dr[x]);
}
writer.WriteEndArray();
}
writer.WriteEndArray();
writer.WriteEndObject();
}
}
这是一个演示它的工作小提琴。有关详细信息,请参阅有关自定义 JsonConverter 的 Newtonsoft 文档。
数据表Json转换器
将DataTable
转换为自定义 JSON 字符串。
public class DataTableJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter w, object v, JsonSerializer s)
{
w.WriteStartObject();
w.WritePropertyName("data");
w.WriteStartArray();
foreach(DataRow r in (v as DataTable).Rows)
{
w.WriteStartArray();
foreach(var c in r.ItemArray)
{
w.WriteValue(c);
}
w.WriteEndArray();
}
w.WriteEndArray();
w.WriteEndObject();
}
public override object ReadJson(JsonReader r, Type t, object v, JsonSerializer s)
{
throw new NotImplementedException("Unnecessary: CanRead is false.");
}
public override bool CanRead { get { return false; } }
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DataTable);
}
}
这是如何使用它
public class Program
{
public static void Main()
{
var dt = SeedData();
var json = JsonConvert.SerializeObject(
dt, Newtonsoft.Json.Formatting.Indented,
new DataTableJsonConverter());
Console.WriteLine(json);
}
public static DataTable SeedData()
{
var dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Position");
for (var i = 0; i < 2; ++i)
{
dt.Rows.Add(new object[] { "Shaun", "Developer" });
}
return dt;
}
}
这是它的输出
{
"data": [
[
"Shaun",
"Developer"
],
[
"Shaun",
"Developer"
]
]
}
性能
对于那些感兴趣的人,这里有一个小提琴的分支,它试图展示我、dbc 和Warheat1990 超过 1500 个数据行,每个行运行两次。它们都非常接近,由于我不知道的原因,第二次运行总是更快。
DataTableJsonConverter:6 ms
DataTableJsonConverter:2 ms
DataTableTo2dArrayConverter:251 ms
DataTableTo2dArrayConverter:11 ms
JqueryDatatablesConverter:1580 ms
JqueryDatatablesConverter:16 ms