using System.Collections.Generic;
using Newtonsoft.Json.Linq;
public static void Main()
{""RowNumber"":1,""ID"":4289,""Assets Variance"":100,""Rules Diff"":10.72,""TotalFunding"":43.22},
{""RowNumber"":2,""ID"":4233,""Assets Variance"":75,""Rules Diff"":6.7,""TotalFunding"":0},
{""RowNumber"":3,""ID"":2222,""Assets Variance"":43,""Rules Diff"":6.7,""TotalFunding"":0}
DataTable dt = JsonConvert.DeserializeObject<DataTable>(data, new ReadAheadDataTableConverter());
static void DumpTable(DataTable dt)
foreach (DataRow row in dt.Rows)
foreach (DataColumn col in dt.Columns)
Console.WriteLine(col.ColumnName + " (" + col.DataType.Name + ") : " + row[col]);
public class ReadAheadDataTableConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(DataTable);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
JArray array = JArray.Load(reader);
var dataTypes = DetermineColumnDataTypes(array);
var table = BuildDataTable(array, dataTypes);
private DataTable BuildDataTable(JArray array, Dictionary<string, Type> dataTypes)
DataTable table = new DataTable();
foreach (var kvp in dataTypes)
table.Columns.Add(kvp.Key, kvp.Value);
foreach (JObject item in array.Children<JObject>())
DataRow row = table.NewRow();
foreach (JProperty prop in item.Properties())
if (prop.Value.Type != JTokenType.Null)
Type dataType = dataTypes[prop.Name];
row[prop.Name] = prop.Value.ToObject(dataType);
private Dictionary<string, Type> DetermineColumnDataTypes(JArray array)
var dataTypes = new Dictionary<string, Type>();
foreach (JObject item in array.Children<JObject>())
foreach (JProperty prop in item.Properties())
Type currentType = GetDataType(prop.Value.Type);
if (!dataTypes.TryGetValue(prop.Name, out previousType) ||
(previousType == typeof(long) && currentType == typeof(decimal)))
dataTypes[prop.Name] = currentType;
else if (previousType == typeof(decimal) && currentType == typeof(long))
dataTypes[prop.Name] = previousType;
else if (previousType != currentType)
dataTypes[prop.Name] = typeof(string);
private Type GetDataType(JTokenType tokenType)
case JTokenType.TimeSpan:
throw new JsonException("This converter does not support complex types");
public override bool CanWrite
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();