这个问题
似乎是,Newtonsoft的
DataSetConverter使用会有限制Newtonsoft的
DataTableConverter做
DataTableConverterconverter = new DataTableConverter();,然后调用它的
ReadJson()直接方法。因此,永远不会使用您的转换器。
一种解决方案 是
DataSetConverter通过改编James Newton-
King的原始代码来创建自己的版本:
public class DataSetConverter<TDataTableConverter> : DataSetConverter where TDataTableConverter : JsonConverter, new(){ // This pre adapted from // https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Converters/DataSetConverter.cs // Copyright (c) 2007 James Newton-King // Licensed under The MIT License (MIT): // https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md readonly TDataTableConverter converter = new TDataTableConverter(); public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } // handle typed datasets DataSet ds = (objectType == typeof(DataSet)) ? new DataSet() : (DataSet)Activator.CreateInstance(objectType); reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { DataTable dt = ds.Tables[(string)reader.Value]; bool exists = (dt != null); dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer); if (!exists) { ds.Tables.Add(dt); } reader.ReadAndAssert(); } return ds; }}public static class JsonReaderExtensions{ public static void ReadAndAssert(this JsonReader reader) { if (reader == null) throw new ArgumentNullException(); if (!reader.Read()) { new JsonReaderException(string.Format("Unexpected end at path {0}", reader.Path)); } }}然后添加
DataSetConverter<TypeInferringDataTableConverter>到您的转换器列表。
顺便说一句,如果您需要做的就是将列类型设置为,
DateTime当列名包含字符串时
"date",您可以考虑创建一个比转换过程更简单的转换
TypeInferringDataTableConverter器,以反序列化缺少第一列的数据表:
- 分叉的代码
DataTableConverter
。开始时请注意许可证:
// Permission is hereby granted, free of charge, to any person// obtaining a copy of this software and associated documentation// files (the "Software"), to deal in the Software without// restriction, including without limitation the rights to use,// copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the// Software is furnished to do so, subject to the following// conditions://// The above copyright notice and this permission notice shall be// included in all copies or substantial portions of the Software.//// ...
让您的分叉转换器子类为Newtonsoft的子类
DataTableConverter
;删除的所有代码WriteJson()
。修改
GetColumnDataType()
以传递列名并添加必要的逻辑:private static Type GetColumnDataType(JsonReader reader, string columnName)
{
JsonToken tokenType = reader.TokenType;switch (tokenType){ case JsonToken.String: if (columnName.IndexOf("date", StringComparison.OrdinalIgnoreCase) >= 0) return typeof(DateTime); return reader.ValueType; case JsonToken.Integer: case JsonToken.Boolean: case JsonToken.Float: case JsonToken.Date: case JsonToken.Bytes: return reader.ValueType; case JsonToken.Null: case JsonToken.Undefined: if (columnName.IndexOf("date", StringComparison.OrdinalIgnoreCase) >= 0) return typeof(DateTime); return typeof(string); case JsonToken.StartArray: reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartObject) { return typeof(DataTable); // nested datatable } Type arrayType = GetColumnDataType(reader, columnName); return arrayType.MakeArrayType(); default: throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType));}}
然后将调用固定为
GetColumnDataType()
在第152行附近传递列名称:Type columnType = GetColumnDataType(reader, columnName);
存根在任何丢失内部的方法,如
ReadAndAssert()
与如图静态扩展方法在这里
*创建您自己的Newtonsoft转换器版本 *的替代解决方案
是,在
[OnDeserialized]容器类的事件中,使用的其中一个,循环遍历的所有表中的所有
DataSet列,并将名称包含为
string(或
object)类型的列转换为列。如何更改数据表中数据列的数据类型的答案?。
"date"``DateTime



