2

I want to serialize to JSON a .NET DataTable with RowError and column errors. I do something like this:

var dt = new DataTable();
dt.Columns.Add("Col1");

dt.Rows.Add("A");

dt.Rows[0].RowError = "Test row error";
dt.Rows[0].SetColumnError(0, "Test column error");

var json = JsonConvert.SerializeObject(dt);

The resulting JSON looks like this:

[{"Col1":"A"}]

No RowError or column errors information is included.

Is there a way to serialize DataTable with "error" information included?

Thanks.

Trevor
  • 7,777
  • 6
  • 31
  • 50
user1044169
  • 2,686
  • 6
  • 35
  • 64
  • I've never looked at it, but I presume that your serializer treats a datatable differently based on the indication that it does serialize the column value, which *isn't* a property but doesn't serialize things that are properties, which is something of a difference to other(normal) objects where props are serialized and nonprops aren't.. – Caius Jard Feb 27 '21 at 19:05
  • https://stackoverflow.com/questions/43315700/json-net-how-to-serialize-just-one-row-from-a-datatable-object-without-it-being Looks helpful/interesting – Caius Jard Feb 27 '21 at 19:09

1 Answers1

1

I want to serialize to JSON a .NET DataTable with RowError and column errors

By default as you have seen, only the ColumnName and it's value are serialized. To include other properties that you want, you can do this by writing your own JsonConverter class, please see Custom JsonConverter for more information. You'll need to have two converter's, one for the DataTable and another for the DataRow.

*Please note that each class will need to have this namespace: using Newtonsoft.Json;

CustomDataTableConverter

public class CustomDataTableConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType) => 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)
        {
            DataTable table = value as DataTable;
            CustomDataRowConverter converter = new CustomDataRowConverter();

            writer.WriteStartObject();

            writer.WritePropertyName("DataRows");
            writer.WriteStartArray();

            foreach (DataRow row in table.Rows)
            {
                converter.WriteJson(writer, row, serializer);
            }

            writer.WriteEndArray();
            writer.WriteEndObject();
        }
    }

CustomDataRowConverter

public class CustomDataRowConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType) => typeof(DataRow).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)
        {
            DataRow row = value as DataRow;
            JsonSerializer ser = new JsonSerializer();
            writer.WriteStartObject();

            // Serializes the row error property
            writer.WritePropertyName(nameof(row.RowError));
            ser.Serialize(writer, row.RowError);

            foreach (DataColumn column in row.Table.Columns)
            {
                writer.WritePropertyName(column.ColumnName);
                ser.Serialize(writer, row[column]);

                // Serialize the columns error description
                writer.WritePropertyName("ColumnError");
                ser.Serialize(writer, row.GetColumnError(column));
            }

            writer.WriteEndObject();
        }
    }

Now that you have the needed converters, here's how you use them in your case. Please note, I added another datarow to show the difference here.

 var dt = new DataTable();
 dt.Columns.Add("Col1");

 dt.Rows.Add("A");
 dt.Rows.Add("B");

 dt.Rows[0].RowError = "Test row error";
 dt.Rows[0].SetColumnError(0, "Test column error");

 dt.Rows[1].RowError = "Test row error B";
 dt.Rows[1].SetColumnError(0, "Test column error B");

 JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
 jsonSerializerSettings.Converters.Add(new CustomDataTableConverter());
 jsonSerializerSettings.Converters.Add(new CustomDataRowConverter());

 var json = JsonConvert.SerializeObject(dt, Formatting.Indented, jsonSerializerSettings);

When this runs, my output looks like:

{
  "DataRows": [
    {
      "RowError": "Test row error",
      "Col1": "A",
      "ColumnError": "Test column error"
    },
    {
      "RowError": "Test row error B",
      "Col1": "B",
      "ColumnError": "Test column error B"
    }
  ]
}

Also something to remember, I didn't do the deserialize part of this, only the serialization part, but it's similar.

Trevor
  • 7,777
  • 6
  • 31
  • 50