我正在尝试将.NET DataTable序列化为JSON文件,然后将JSON文件反序列化为DataTable。我想很简单。
但是,我有一个表,3行3列,每个元素的类型都是double。如果第一行中的任何值为null,则当JSON.Net将json文件反序列化为DataTable对象时,第一行中为null的列的所有值都变为字符串。
需要明确的是,只有第一行的值为空时,才会发生这种情况。如果除第一行外的任何其他行中的任何值均为null,则该列中的其余值将保持为双精度。
如果我将null替换为double,那么一切都会按预期进行(但是,我无法执行此操作)。
如果我设置NullValueHandling = NullValueHandling.Ignore,则所有值都保持为双精度,除了第一行现在列为最后一行:
例:
"Column2": 1.0,
"Column3": 1.1
},
{
"Column1": 0.0,
"Column2": 0.5,
"Column3": 2.0
},
成为:
"Column2": 1.0,
"Column3": 1.1
},
{
"Column2": 0.5,
"Column3": 2.0,
"Column1": 0.0
},
我需要能够反序列化JSON,保持Columns的顺序,并且第一行中没有空值,导致该行中的所有值都变成字符串。我还需要保持第一行的Column1(在上述情况下)为空-
不管它是空字符串还是DBNull。
有什么想法吗?(我的测试代码在下面。.comment/ uncomment NullValueHandling看问题)
DataTable table = new DataTable("MyTable");
table.Columns.Add("Column1", typeof(double));
table.Columns.Add("Column2", typeof(double));
table.Columns.Add("Column3", typeof(double));
for (int i = 0; i < 10; i++) {
if (i == 0)
table.Rows.Add(null, 1.0, 1.1);
else
table.Rows.Add(0.0, 0.5, 2.0);
}
JsonSerializer serializer = new JsonSerializer();
//serializer.TypeNameHandling = TypeNameHandling.All;
serializer.NullValueHandling = NullValueHandling.Ignore;
using (StreamWriter sw1 = new StreamWriter("1st.json"))
using (JsonWriter writer1 = new JsonTextWriter(sw1))
{
writer1.Formatting = Formatting.Indented;
serializer.Serialize(writer1, table);
}
DataTable newtable;
using (StreamReader sr = new StreamReader("1st.json"))
using (JsonReader reader = new JsonTextReader(sr))
{
newtable = (DataTable)serializer.Deserialize(reader, typeof(DataTable));
}
using (StreamWriter sw = new StreamWriter("3rd.json"))
using (JsonWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
serializer.Serialize(writer, newtable);
}
Json.NET是根据MIT许可证开放的源代码,因此一种可能性是创建一个DataTableConverter
适合您需要的修改版本。其源代码可在此处获得。
首先,创建您自己的此类的派生版本,称为JsonDefaultTypeDataTableConverter<T>
。修改方法GetColumnDataType
以返回typeof(T)
空列值:
/// <summary>
/// Converts a <see cref="DataTable"/> to and from JSON.
/// Adapted from https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Converters/DataTableConverter.cs
/// </summary>
public class JsonDefaultTypeDataTableConverter<T> : JsonConverter
{
private static Type GetColumnDataType(JsonReader reader)
{
JsonToken tokenType = reader.TokenType;
switch (tokenType)
{
case JsonToken.Integer:
case JsonToken.Boolean:
case JsonToken.Float:
case JsonToken.String:
case JsonToken.Date:
case JsonToken.Bytes:
return reader.ValueType;
case JsonToken.Null:
case JsonToken.Undefined:
return typeof(T); // WAS typeof(string).
case JsonToken.StartArray:
CheckedRead(reader);
if (reader.TokenType == JsonToken.StartObject)
{
return typeof (DataTable); // nested datatable
}
Type arrayType = GetColumnDataType(reader);
return arrayType.MakeArrayType();
default:
throw new JsonSerializationException(string.Format("Unexpected JSON token when reading DataTable: {0}", tokenType));
}
}
}
您还需要修复调用以JsonSerializationException
在第232行周围抛出a
,例如,如下所示:
private static void CheckedRead(JsonReader reader)
{
if (!reader.Read())
{
throw new JsonSerializationException(string.Format("Unexpected end when reading DataTable."));
}
}
并且,围绕第114行:
if (reader.TokenType != JsonToken.StartArray)
{
throw new JsonSerializationException(string.Format("Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.", reader.TokenType));
}
现在,假设您 知道 表包含double
值的列,则可以这样使用它:
JsonSerializer serializer = new JsonSerializer();
//serializer.TypeNameHandling = TypeNameHandling.All;
//serializer.NullValueHandling = NullValueHandling.Ignore; -- DO NOT USE THIS OPTION.
serializer.Converters.Add(new JsonDefaultTypeDataTableConverter<double>());
请注意,这样做并不是在修改Json.NET本身的内部结构,而是在为常用的.Net类型复制和修改其一组标准转换器。
更新:完整版本在这里。
我的JSON字符串是: 我想要实现的是,当JSON中没有提供schemaVersion时,能够在默认情况下反序列化到SubClassV1,但即使在Superclass中将schemaVersion初始化为“1.0”时,我仍然会收到以下错误:
我正在尝试为接受JSON输入的前端库创建一个java SDK。本质上,此SDK将特定类型的对象转换为JSON,然后由前端库使用。 我正在使用杰克逊的多态序列化/反序列化使用它的注释系统。 我有一个基类a和扩展a的两个子类B和C。类a有一个类型字段,我用它来决定要使用哪个类(B或C)。语法如下所示: 现在,当我使用Jackson的ObjectMapper函数读取字符串化的JSON并转换为类A时,我根
我正在尝试使用kryo序列化和反序列化到二进制。我想我已经完成了序列化,但似乎无法反序列化。下面是我正在处理的代码,但最终我想存储一个字节[],然后再次读取它。文档只显示了如何使用文件。
问题内容: 我像这样反序列化json: 有效负载类型取决于类型。我的课: 我也输入了没有有效载荷的“ d”。如果我尝试反序列化: 它可以工作,但不能在没有有效负载的情况下工作: 如何使其与上一个示例一起使用? 我得到的错误的Stacktrace: 问题答案: 我也遇到了这个问题,找不到利用杰克逊(定制提供的机制的一流解决方案,等等)。 看起来像是处理外部类型ID的方式中的错误。我通过以下方法解决了
我像这样反序列化jsons: 其中负载类型取决于类型。我的班级: 我得到的错误的堆栈跟踪:
问题内容: 我有一个由数据库支持的小应用程序(SQLite,但与问题无关)。我已经定义了一些类型,例如: 这些类型映射到数据库中的表。当我读取数据时,我最终会写出这样的函数: (为了清楚起见,我省略了处理错误。) 编写这样的函数确实很烦人,感觉就像创建了很多样板。有没有更惯用的方法将一组SqlValues转换为Haskell数据? 问题答案: 库中似乎没有任何标准方法可用于此目的。如果您感觉特别敏