【问题标题】:How can I deserialize an ADO.NET DataTable that contains null values using Json.NET?如何使用 Json.NET 反序列化包含空值的 ADO.NET DataTable?
【发布时间】:2011-05-05 18:17:57
【问题描述】:

我正在尝试使用 Newtonsoft.Json.Net35 版本 4.0.2.0 反序列化包含空值的 ADO.NET 数据表。序列化工作正常:

    [Test]
    public void SerializeDataTableWithNull()
    {
        var table = new DataTable();
        table.Columns.Add("item");
        table.Columns.Add("price", typeof(double));
        table.Rows.Add("shirt", 49.99);
        table.Rows.Add("pants", 54.99);
        table.Rows.Add("shoes"); // no price

        var json = JsonConvert.SerializeObject(table);
        Assert.AreEqual(@"["
            + @"{""item"":""shirt"",""price"":49.99},"
            + @"{""item"":""pants"",""price"":54.99},"
            + @"{""item"":""shoes"",""price"":null}]", json);
    }

如果缺少值,反序列化可以正常工作:

    [Test]
    public void DerializeDataTableWithImplicitNull()
    {
        const string json = @"["
            + @"{""item"":""shirt"",""price"":49.99},"
            + @"{""item"":""pants"",""price"":54.99},"
            + @"{""item"":""shoes""}]";
        var table = JsonConvert.DeserializeObject<DataTable>(json);
        Assert.AreEqual("shirt", table.Rows[0]["item"]);
        Assert.AreEqual("pants", table.Rows[1]["item"]);
        Assert.AreEqual("shoes", table.Rows[2]["item"]);
        Assert.AreEqual(49.99, (double)table.Rows[0]["price"], 0.01);
        Assert.AreEqual(54.99, (double)table.Rows[1]["price"], 0.01);
        Assert.IsInstanceOf(typeof(System.DBNull), table.Rows[2]["price"]);
    }

但是,如果值显式为 null:

    [Test]
    public void DerializeDataTableWithExplicitNull()
    {
        const string json = @"["
            + @"{""item"":""shirt"",""price"":49.99},"
            + @"{""item"":""pants"",""price"":54.99},"
            + @"{""item"":""shoes"",""price"":null}]";
        var table = JsonConvert.DeserializeObject<DataTable>(json);
        Assert.AreEqual("shirt", table.Rows[0]["item"]);
        Assert.AreEqual("pants", table.Rows[1]["item"]);
        Assert.AreEqual("shoes", table.Rows[2]["item"]);
        Assert.AreEqual(49.99, (double)table.Rows[0]["price"], 0.01);
        Assert.AreEqual(54.99, (double)table.Rows[1]["price"], 0.01);
        Assert.IsInstanceOf(typeof(System.DBNull), table.Rows[2]["price"]);
    }

DeserializeObject 抛出“System.ArgumentException:无法将列 'price' 设置为空。请改用 DBNull。”以下解决方法适用于我的特定 JSON:

        var regex = new Regex(@",?""[_\w]+"":null");
        var nullless = regex.Replace(json, string.Empty);
        var table = JsonConvert.DeserializeObject<DataTable>(nullless);

但就像所有基于正则表达式的组件一样,这显然很脆弱。

最后,问题:

  1. 这是一个错误吗?
  2. Json.NET 有许多可以挂钩的事件。有没有办法在遇到空值并将值显式设置为 System.DBNull 时收到通知?

提前致谢,

弗兰克

【问题讨论】:

    标签: ado.net json.net


    【解决方案1】:

    看起来这是一个很容易通过替换来修复的错误

    dr[columnName] = reader.Value
    

    dr[columnName] = reader.Value ?? System.DBNull.Value
    

    Newtonsoft.Json.Converters.DataTableConverter。我在跟踪器中输入了issue

    【讨论】:

    • fixed。谢谢詹姆斯。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多