使用 json.net 中的属性序列化 DataSet/DataTable
Posted
技术标签:
【中文标题】使用 json.net 中的属性序列化 DataSet/DataTable【英文标题】:Serializing a DataSet/DataTable with properties in json.net 【发布时间】:2014-07-14 17:36:31 【问题描述】:我正在寻找将数据集序列化为 json 的解决方案,但我需要获取 json 中的行状态。
json.net 是否序列化/反序列化数据集/数据表的属性,例如 rowstate?我只能找到具有行值的示例。
谢谢。
【问题讨论】:
【参考方案1】:不,Json.Net 附带的DataTableConverter
不会序列化RowState
。如果你真的需要 JSON 中的这个值,应该可以创建一个自定义的JsonConverter
来输出它。但是,由于RowState
是只读属性,因此无法将其反序列化回其原始值。 (其实这个值是通过各种内部状态变量计算出来的。)
【讨论】:
【参考方案2】:我为 DataSet 编写了一个自定义转换器,用于保持行状态。 DataSet 类可以用WriteXmlSchema 将schema 写为xml,它可以用WriteXml(sw, XmlWriteMode.DiffGram) 写包括rowstate 的数据。这会生成两个字符串,它们是 DataSetSerializer 类中的属性,然后可以使用 JsonSerializer 对其进行序列化和反序列化。这是一个测试类中的代码:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Data;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TestProject3
public class DataSetConverter : JsonConverter<DataSet>
private class DataSetSerializer
public string SchemaString get; set;
public string DataString get; set;
private static string GetSchema(DataSet ds)
using (var sw = new StringWriter())
ds.WriteXmlSchema(sw);
return sw.ToString();
private static string GetData(DataSet ds)
using (var sw = new StringWriter())
ds.WriteXml(sw, XmlWriteMode.DiffGram);
return sw.ToString();
private DataSet GetDataSet()
var ds = new DataSet();
using (var sr1 = new StringReader(SchemaString))
ds.ReadXmlSchema(sr1);
using (var sr2 = new StringReader(DataString))
ds.ReadXml(sr2, XmlReadMode.DiffGram);
return ds;
public static string Serialize(DataSet ds)
var serializer = new DataSetSerializer() SchemaString = GetSchema(ds), DataString = GetData(ds) ;
return JsonSerializer.Serialize<DataSetSerializer>(serializer);
public static DataSet DeSerialize(string s)
var serializer = JsonSerializer.Deserialize<DataSetSerializer>(s);
return serializer.GetDataSet();
public override DataSet Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
return DataSetSerializer.DeSerialize(reader.GetString());
public override void Write(Utf8JsonWriter writer, DataSet value, JsonSerializerOptions options)
writer.WriteStringValue(DataSetSerializer.Serialize(value));
[TestClass]
public class TestDataSet
private DataSet CreateTestDataSet()
var ds = new DataSet();
var dt = ds.Tables.Add();
dt.Columns.Add("A");
dt.Columns.Add("B");
dt.Rows.Add("A1", "B1");
var dr = dt.Rows.Add("A2", "B2");
ds.AcceptChanges();
dr["A"] = "AA2";
return ds;
private void CheckTestDataSet(DataSet ds)
var dt = ds.Tables[0];
Assert.IsTrue(dt.Rows[0].RowState == DataRowState.Unchanged && dt.Rows[1].RowState == DataRowState.Modified);
[TestMethod]
public void TestDataSetConverter()
var ds = CreateTestDataSet();
var serializeOptions = new JsonSerializerOptions Converters = new DataSetConverter() ;
var jsonstring = JsonSerializer.Serialize(ds, serializeOptions);
ds = JsonSerializer.Deserialize<DataSet>(jsonstring, serializeOptions);
CheckTestDataSet(ds);
【讨论】:
【参考方案3】:我需要一个解决方案,为 DataSets
和 DataTables
维护 RowState
,以便从 SOAP 调用迁移到 WebApi 调用但使用 Newtonsoft 而不是 System.Text.Json
的遗留应用程序。谢谢Alex 的最后一个答案,这正是我所需要的。
这是同一事物的 Newtonsoft 版本:
using System;
using System.Data;
using System.IO;
using Newtonsoft.Json;
using Xunit;
namespace DataSetsAndTablesTester
public class CustomJsonConverter_DataSet : JsonConverter<DataSet>
private class DataSetSerializer
public string SchemaString get; set;
public string DataString get; set;
private static string GetSchema(DataSet ds)
using (var sw = new StringWriter())
ds.WriteXmlSchema(sw);
return sw.ToString();
private static string GetData(DataSet ds)
using (var sw = new StringWriter())
ds.WriteXml(sw, XmlWriteMode.DiffGram);
return sw.ToString();
private DataSet GetDataSet()
var ds = new DataSet();
using (var sr1 = new StringReader(SchemaString))
ds.ReadXmlSchema(sr1);
using (var sr2 = new StringReader(DataString))
ds.ReadXml(sr2, XmlReadMode.DiffGram);
return ds;
public static string Serialize(DataSet ds)
var serializer = new DataSetSerializer() SchemaString = GetSchema(ds), DataString = GetData(ds) ;
return JsonConvert.SerializeObject(serializer);
public static DataSet DeSerialize(string s)
var serializer = JsonConvert.DeserializeObject<DataSetSerializer>(s);
return serializer.GetDataSet();
public override void WriteJson(JsonWriter writer, DataSet value, JsonSerializer serializer)
if (value == null)
throw new Exception("Passed in DataSet is null");
writer.WriteValue(DataSetSerializer.Serialize(ds: value));
public override DataSet ReadJson(JsonReader reader, Type objectType, DataSet existingValue, bool hasExistingValue, JsonSerializer serializer)
return DataSetSerializer.DeSerialize((string)reader.Value);
public class CustomJsonConverter_DataTable : JsonConverter<DataTable>
private class DataTableSerializer
public string SchemaString get; set;
public string DataString get; set;
private static string GetSchema(DataTable dt)
using (var sw = new StringWriter())
dt.WriteXmlSchema(sw);
return sw.ToString();
private static string GetData(DataTable dt)
using (var sw = new StringWriter())
dt.WriteXml(sw, XmlWriteMode.DiffGram);
return sw.ToString();
private DataTable GetDataTable()
var dt = new DataTable();
using (var sr1 = new StringReader(SchemaString))
dt.ReadXmlSchema(sr1);
using (var sr2 = new StringReader(DataString))
dt.ReadXml(sr2);
return dt;
public static string Serialize(DataTable dt)
var serializer = new DataTableSerializer() SchemaString = GetSchema(dt), DataString = GetData(dt) ;
return JsonConvert.SerializeObject(serializer);
public static DataTable DeSerialize(string s)
var serializer = JsonConvert.DeserializeObject<DataTableSerializer>(s);
return serializer.GetDataTable();
public override void WriteJson(JsonWriter writer, DataTable value, JsonSerializer serializer)
if (value == null)
throw new Exception("Passed in DataTable is null");
if (string.IsNullOrEmpty(value.TableName))
throw new Exception("Passed in DataTable Name is null or empty");
writer.WriteValue(DataTableSerializer.Serialize(dt: value));
public override DataTable ReadJson(JsonReader reader, Type objectType, DataTable existingValue, bool hasExistingValue, JsonSerializer serializer)
return DataTableSerializer.DeSerialize((string)reader.Value);
public class JsonConverterTester
public void TestJsonDataSetConverter()
DataSet ds = CreateTestDataSet();
String json = JsonConvert.SerializeObject(value: ds, converters: new CustomJsonConverter_DataSet());
Console.WriteLine(json);
DataSet ds2 = JsonConvert.DeserializeObject<DataSet>(value: json, converters: new CustomJsonConverter_DataSet());
CheckTestDataSet(ds2);
public void TestJsonDataTableConverter()
DataTable dt = CreateTestDataTable();
String json = JsonConvert.SerializeObject(value: dt, converters: new CustomJsonConverter_DataTable());
Console.WriteLine(json);
DataTable dt2 = JsonConvert.DeserializeObject<DataTable>(value: json, converters: new CustomJsonConverter_DataTable());
CheckTestDataTable(dt2);
private DataSet CreateTestDataSet()
var ds = new DataSet();
var dt = ds.Tables.Add();
dt.Columns.Add("A");
dt.Columns.Add("B");
dt.Rows.Add("A1", "B1");
var dr = dt.Rows.Add("A2", "B2");
ds.AcceptChanges();
dr["A"] = "AA2";
return ds;
private void CheckTestDataSet(DataSet ds)
var dt = ds.Tables[0];
Assert.True(dt.Rows[0].RowState == DataRowState.Unchanged && dt.Rows[1].RowState == DataRowState.Modified);
private DataTable CreateTestDataTable()
var dt = new DataTable();
dt.TableName = "TestTable";
dt.Columns.Add("A");
dt.Columns.Add("B");
dt.Rows.Add("A1", "B1");
var dr = dt.Rows.Add("A2", "B2");
dt.AcceptChanges();
dr["A"] = "AA2";
return dt;
private void CheckTestDataTable(DataTable dt)
Assert.True(dt.Rows[0].RowState == DataRowState.Unchanged && dt.Rows[1].RowState == DataRowState.Modified);
【讨论】:
以上是关于使用 json.net 中的属性序列化 DataSet/DataTable的主要内容,如果未能解决你的问题,请参考以下文章
使用 Json.Net 作为 MVC 中的默认格式化程序,而不是 API [重复]