1、原因
原生Json反序列化时,如果多行数据第一行为int,后面多行为decimal会字段转化为int
demo文件,保存为到 E:/aa.txt:
http://cdn01.pukuimin.top/zb_users/upload/2018/jsonToDataTableDemo.txt
转为DataTable时,值自动变了:
转换为List Dictionary时,值正常。
2、解决方法
自定义DataTableConverter方法
public class CustomDataTableJsonConverter : DataTableConverter { /// <summary> /// 反序列化时根据数据类型获取DataTable列类型 /// </summary> /// <param name="tokenType">数据类型</param> /// <returns></returns> private static Type GetColumnDataType(JsonToken tokenType) { switch (tokenType) { // 将整数列按字符串处理,解决JavaScript中具有精度的数字 // 以字符串显示后与实际列类型冲突的问题。 case JsonToken.Integer: return typeof(double); case JsonToken.Float: return typeof(double); case JsonToken.String: case JsonToken.Null: case JsonToken.Undefined: return typeof(string); case JsonToken.Boolean: return typeof(bool); case JsonToken.Date: return typeof(DateTime); } throw new ArgumentOutOfRangeException(); } /// <summary> /// 复写JSON反序列化方法。 /// </summary> public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { DataTable table; if (reader.TokenType == JsonToken.PropertyName) { table = new DataTable((string)reader.Value); reader.Read(); } else { table = new DataTable(); } reader.Read(); while (reader.TokenType == JsonToken.StartObject) { DataRow row = table.NewRow(); reader.Read(); while (reader.TokenType == JsonToken.PropertyName) { string name = (string)reader.Value; reader.Read(); // 根据JSON数据获取Table列类型。 Type columnDataType = GetColumnDataType(reader.TokenType); // 如果Table列集合中尚不包含此列,则将列加入到Table中。 if (!table.Columns.Contains(name)) { table.Columns.Add(new DataColumn(name, columnDataType)); } // 如果列类型为字符串类型。 if (table.Columns[name].DataType == typeof(string)) { // 读取JSON数据。 string value = Convert.ToString(reader.Value); // 如果JSON数据长度大于4,对前端转义后的尖括号进行还原。 // 解决字符在前端验证通过后,因为转义使长度变长,导致存储到数据库时长度溢出的问题。 if (value.Length >= 4) { value = value.Replace("<", "<").Replace(">", ">"); } row[name] = value; } else { row[name] = reader.Value == null ? DBNull.Value : reader.Value; } reader.Read(); } row.EndEdit(); table.Rows.Add(row); reader.Read(); } reader.Read(); return table; } }
修改封装的数据转换方法:
/// <summary> /// Json字符串转换为具体对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="jsonStr"></param> /// <returns></returns> public static T FromJsonTo<T>(string jsonStr) { if (string.IsNullOrWhiteSpace(jsonStr)) return default(T); JsonSerializerSettings setting=new JsonSerializerSettings { //空值处理 NullValueHandling = NullValueHandling.Include, MaxDepth = 10, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, Formatting = Newtonsoft.Json.Formatting.Indented,//缩进 }; if (typeof(T) == typeof(DataTable)) { setting.Converters.Add(new CustomDataTableJsonConverter()); } return JsonConvert.DeserializeObject<T>(jsonStr, setting); }
修改后,转换的DataTable值正常。