using Newtonsoft.Json.Linq;
public static void Main()
DataTable dt = new DataTable();
dt.Columns.Add("PackageID", typeof(int));
dt.Columns.Add("Amount", typeof(int));
dt.Columns.Add("Auto_sync", typeof(bool));
dt.Columns.Add("Color", typeof(string));
dt.Rows.Add(new object[] { 226, null, true, "BLUE" });
dt.Rows.Add(new object[] { 500, 15000, true, "PEACH" });
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new CustomDataTableConverter());
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
string json = JsonConvert.SerializeObject(foo, settings);
Foo foo2 = JsonConvert.DeserializeObject<Foo>(json, settings);
Console.WriteLine("BrokerID: " + foo2.BrokerID);
Console.WriteLine("AccountID: " + foo2.AccountID);
Console.WriteLine("Packages table:");
Console.WriteLine(" " + string.Join(", ",
.Select(c => c.ColumnName + " (" + c.DataType.Name + ")")));
foreach (DataRow row in foo2.Packages.Rows)
Console.WriteLine(" " + string.Join(", ", row.ItemArray
.Select(v => v != null ? v.ToString() : "(null)")));
public string BrokerID { get; set; }
public string AccountID { get; set; }
public DataTable Packages { get; set; }
class CustomDataTableConverter : JsonConverter
public override bool CanConvert(Type objectType)
return (objectType == typeof(DataTable));
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
DataTable dt = (DataTable)value;
JObject metaDataObj = new JObject();
foreach (DataColumn col in dt.Columns)
metaDataObj.Add(col.ColumnName, col.DataType.AssemblyQualifiedName);
JArray rowsArray = new JArray();
rowsArray.Add(metaDataObj);
foreach (DataRow row in dt.Rows)
JObject rowDataObj = new JObject();
foreach (DataColumn col in dt.Columns)
rowDataObj.Add(col.ColumnName, JToken.FromObject(row[col]));
rowsArray.Add(rowDataObj);
rowsArray.WriteTo(writer);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
JArray rowsArray = JArray.Load(reader);
JObject metaDataObj = (JObject)rowsArray.First();
DataTable dt = new DataTable();
foreach (JProperty prop in metaDataObj.Properties())
dt.Columns.Add(prop.Name, Type.GetType((string)prop.Value, throwOnError: true));
foreach (JObject rowDataObj in rowsArray.Skip(1))
DataRow row = dt.NewRow();
foreach (DataColumn col in dt.Columns)
if (rowDataObj[col.ColumnName].Type != JTokenType.Null)
row[col] = rowDataObj[col.ColumnName].ToObject(col.DataType);