反序列化缺少第一列的数据表



我试图将。net数据表序列化为JSON文件,然后将JSON文件反序列化回数据表。我认为相当简单。

然而,我有一个表,3行3列,每个元素都是double类型。如果第一行中的任何值为空,则JSON。Net将json文件反序列化为DataTable对象,第一行中为空的列的所有值都变成字符串。

要清楚,只有当第一行中的值为空时才会发生这种情况。如果在除第一行以外的任何行中有任何值为空,则该列中的其余值仍然为双精度。

  1. 如果我用双精度替换null,一切都按预期工作(我不能在我的情况下这样做,然而)。

  2. 如果我设置NullValueHandling = NullValueHandling。忽略,所有值保持双精度,除了第一行现在被列为最后一行:

的例子:

"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进行反序列化,保持列的顺序,并且在第一行中没有空值,因为该行中的所有值都成为字符串。我还需要保持第一行的Column1(在上面的情况下)为空-不管它是空字符串还是DBNull。

任何想法吗?(我的测试代码如下…注释/取消注释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));
        }
    }
}

您还需要修复在第232行附近抛出JsonSerializationException的调用,例如如下:

    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类型。

更新:完整版本在这里

相关内容

  • 没有找到相关文章