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.