2011-05-05 64 views
1

我正在嘗試使用Newtonsoft.Json.Net35版本4.0.2.0來反序列化包含空值的ADO.NET DataTable。序列化工作正常:如何使用Json.NET反序列化包含空值的ADO.NET DataTable?

[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"]); 
    } 

然而,如果值是明確空:

[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:不能將Column'price'設置爲null,請改用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有許多可以掛鉤的事件。是否有一種方法可以在遇到null值時得到通知,並顯式將值設置爲System.DBNull?

由於提前,

弗蘭克

回答

0

看起來這是一個很容易被取代

dr[columnName] = reader.Value 

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

Newtonsoft.Json.Converters.DataTableConverter修正了一個錯誤。我在跟蹤器中輸入了一個issue

+0

[修正](http://json.codeplex.com/SourceControl/changeset/changes/60604)。謝謝詹姆斯。 – Frank 2011-05-07 02:53:03