使用json.net中的属性序列化DataSet / DataTable

时间:2014-07-14 17:36:32

标签: dataset json.net rowstate

我正在寻找将数据集序列化为json的解决方案,但我需要在json中获取rowstate。

json.net是否序列化/反序列化数据集/数据表的属性,比如rowstate?我只能找到行值的例子。

感谢。

3 个答案:

答案 0 :(得分:1)

不,Json.Net附带的DataTableConverter不会序列化RowState。如果您确实需要JSON中的此值,则应该可以创建自定义JsonConverter来输出它。但是,由于它是一个只读属性,因此无法将RowState反序列化回其原始值。 (实际上,这个值是根据各种内部状态变量计算出来的。)

答案 1 :(得分:1)

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

答案 2 :(得分:1)

我需要一个解决方案,为 RowStateDataSets 维护 DataTables,用于从 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);
        }
    }
}