我的问题与这一问题非常相似,但是我没有足够的声誉对原始答案发表评论。
我有一个名为FillPDF的自定义类,该类在服务器上进行序列化并在客户端上反序列化。
FillPDF dsPDF = JsonConvert.DeserializeObject<FillPDF>(json);
该FillPDF
班由一个中DataSet
包含的一个集合属性DataTables
通过阅读原始问题的解决方案,我知道了为什么将DateTime
类型错误地设置为String
。我了解Json.Net
仅通过查看第一行来DataTableConverter
推断每个推断DataColumn.DataType
(我的第一行具有NULL
值)。
我试图从原始问题开始实施解决方案。dbc建议覆盖DataTableConverter
。我已经做到了,并且settings
在序列化和反序列化期间正在使用该对象,如下所示:
// Server
FillPDF pdfData = new FillPDF(strUniqueColID);
var settings = new JsonSerializerSettings { Converters = new[] { new TypeInferringDataTableConverter() } };
string json = JsonConvert.SerializeObject(pdfData, Formatting.Indented,settings);
// Client
var settings = new JsonSerializerSettings { Converters = new[] { new TypeInferringDataTableConverter() } };
FillPDF dsPDF = JsonConvert.DeserializeObject<FillPDF>(json,settings);
但是,我没有收到任何错误,并且我的基础DataTable仍未正确反序列化。我认为这是因为我要序列化/反序列化自定义对象,而不是DataTable
原始问题中的简单对象。
我想做的是:
if(c.ColumnName.toLower().Contains("date"))
{
// Set Column's Type to DateTime because I know all Column Names containing "date" should be of type DateTime
}
大概必须将其添加到重写中TypeInferringDataTableConverter
。
我不太确定从这里要去哪里,所以我急切需要一些帮助!
谢谢,
贾斯汀。
这个问题
似乎是,Newtonsoft的DataSetConverter
使用会有限制Newtonsoft的DataTableConverter
做DataTableConverter converter = new DataTableConverter();
,然后调用它的ReadJson()
直接方法。因此,永远不会使用您的转换器。
一种解决方案 是DataSetConverter
通过改编James Newton-
King的原始代码来创建自己的版本:
public class DataSetConverter<TDataTableConverter> : DataSetConverter where TDataTableConverter : JsonConverter, new()
{
// This code 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
问题内容: 我有一个具有两列的DataTable。ShipmentDate(DateTime)和Count(Int)。在对字符串反序列化之后,我发现如果第一个itemarray值为null,则ShipmentDate的类型将变为字符串。 检查以下示例。除了第一个数组项,两个json字符串都具有相同的数据。 在我的场景中,第一个项目数组的ShipmentDate可以为null,并且将其转换为字符串类
我有一门课是这样的: 但是当我试图序列化它时,我收到一个错误,上面写着“试图序列化java.lang.class:java.lang.字符串。忘记注册一个类型适配器了吗?”。所以我创建了这个适配器: } 并登记如下: 但我还是犯了同样的错误<我做错了什么 适配器的实现看起来正常吗?
是否有一种简单的方法来反序列化可以是或
我有一个JestClient(elasticsearch)响应,我试图将其反序列化为一个对象。该对象包含两个DateTime字段,而在响应中,它们是字符串,因此我得到: 所以,我创建了一个自定义反序列化器来解决这个问题…然而,无论我做什么,我总是得到同样的错误。不知何故它没有注册使用它? 最后,我试图解析JestClient响应的代码: 无论我尝试什么,我总是得到上面的错误,我甚至不确定在这一点上
想象一下以下场景: 我想为Foo编写一个自定义的Jackson反序列化程序。为了做到这一点(例如,为了反序列化具有Foo的类 如何编写这样的反序列化程序?这应该是可能的,因为Jackson是通过键入集合和地图来实现的。 澄清: 似乎有两个部分可以解决这个问题: 1)获取内声明的属性类型并使用它来反序列化
我正在将RedditAPI中的一些内容反序列化到POJO中。我的目标是尽可能简化代码,因为reddit中实体之间的JSON结构通常是相同的。 例如,反序列化链接对象的JSON如下所示: 我可以反序列化这一点没有问题,但由于reddit注释的不同之处在于其类型为t1,并且在其下方的数据对象中具有不同的结构,因此我希望将相同的类结构重新用于JSON包装,而不必创建多个具有一行或两行差异的复制类。 我创