using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PTMedicalInsurance.Helper
{
class ReadDataTableConverter : 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);
return table;
}
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);
}
}
table.Rows.Add(row);
}
return table;
}
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 (currentType != null)
{
Type previousType;
if (!dataTypes.TryGetValue(prop.Name, out previousType) ||
(previousType == typeof(long) && currentType == typeof(decimal)))
{
dataTypes[prop.Name] = currentType;
}
else if (previousType != currentType)
{
dataTypes[prop.Name] = typeof(string);
}
}
}
}
return dataTypes;
}
private Type GetDataType(JTokenType tokenType)
{
switch (tokenType)
{
case JTokenType.Null:
return null;
case JTokenType.String:
return typeof(string);
case JTokenType.Integer:
return typeof(long);
case JTokenType.Float:
return typeof(decimal);
case JTokenType.Boolean:
return typeof(bool);
case JTokenType.Date:
return typeof(DateTime);
case JTokenType.TimeSpan:
return typeof(TimeSpan);
case JTokenType.Guid:
return typeof(Guid);
case JTokenType.Bytes:
return typeof(byte[]);
case JTokenType.Array:
case JTokenType.Object:
throw new JsonException("This converter does not support complex types");
default:
return typeof(string);
}
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}