diff --git a/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs index 12a1f793..3699eb62 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs @@ -106,6 +106,53 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual(2, dt.Rows.Count); } + public class DataSetTestClass + { + public DataSet Set { get; set; } + } + + [Test] + public void SerializeNull() + { + DataSetTestClass c1 = new DataSetTestClass + { + Set = null + }; + + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + + StringAssert.AreEqual(@"{ + ""Set"": null +}", json); + + DataSetTestClass c2 = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(null, c2.Set); + } + + [Test] + public void SerializeNullRoot() + { + string json = JsonConvert.SerializeObject(null, typeof(DataSet), new JsonSerializerSettings + { + Formatting = Formatting.Indented + }); + + StringAssert.AreEqual(@"null", json); + } + + [Test] + public void DeserializeNullTable() + { + string json = @"{ + ""TableName"": null +}"; + + DataSet ds = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(true, ds.Tables.Contains("TableName")); + } + [Test] public void SerializeMultiTableDataSet() { diff --git a/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs index c30a011e..ab3cb8d8 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs @@ -454,6 +454,41 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual("432", dt[0].CustomerID); } + public class DataTableTestClass + { + public DataTable Table { get; set; } + } + + [Test] + public void SerializeNull() + { + DataTableTestClass c1 = new DataTableTestClass + { + Table = null + }; + + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + + StringAssert.AreEqual(@"{ + ""Table"": null +}", json); + + DataTableTestClass c2 = JsonConvert.DeserializeObject(json); + + Assert.AreEqual(null, c2.Table); + } + + [Test] + public void SerializeNullRoot() + { + string json = JsonConvert.SerializeObject(null, typeof(DataTable), new JsonSerializerSettings + { + Formatting = Formatting.Indented + }); + + StringAssert.AreEqual(@"null", json); + } + #if !(NET20 || PORTABLE || PORTABLE40) [Test] public void DeserializedTypedDataTableWithConverter() diff --git a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs index 3bfffffc..d39c6b48 100644 --- a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs @@ -70,6 +70,11 @@ namespace Newtonsoft.Json.Converters /// The object value. 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() @@ -87,7 +92,9 @@ namespace Newtonsoft.Json.Converters dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer); if (!exists) + { ds.Tables.Add(dt); + } CheckedRead(reader); } @@ -110,9 +117,10 @@ namespace Newtonsoft.Json.Converters private void CheckedRead(JsonReader reader) { if (!reader.Read()) + { throw JsonSerializationException.Create(reader, "Unexpected end when reading DataSet."); + } } } } - #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs index 172396cd..41a6b776 100644 --- a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs @@ -80,6 +80,11 @@ namespace Newtonsoft.Json.Converters /// The object value. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { + if (reader.TokenType == JsonToken.Null) + { + return null; + } + DataTable dt = existingValue as DataTable; if (dt == null) @@ -90,15 +95,24 @@ namespace Newtonsoft.Json.Converters : (DataTable)Activator.CreateInstance(objectType); } + // DataTable is inside a DataSet + // populate the name from the property name if (reader.TokenType == JsonToken.PropertyName) { dt.TableName = (string)reader.Value; CheckedRead(reader); + + if (reader.TokenType == JsonToken.Null) + { + return dt; + } } if (reader.TokenType != JsonToken.StartArray) + { throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); + } CheckedRead(reader); @@ -134,7 +148,9 @@ namespace Newtonsoft.Json.Converters if (column.DataType == typeof(DataTable)) { if (reader.TokenType == JsonToken.StartArray) + { CheckedRead(reader); + } DataTable nestedDt = new DataTable(); @@ -150,7 +166,9 @@ namespace Newtonsoft.Json.Converters else if (column.DataType.IsArray && column.DataType != typeof(byte[])) { if (reader.TokenType == JsonToken.StartArray) + { CheckedRead(reader); + } List o = new List(); @@ -196,7 +214,9 @@ namespace Newtonsoft.Json.Converters case JsonToken.StartArray: CheckedRead(reader); if (reader.TokenType == JsonToken.StartObject) - return typeof(DataTable); // nested datatable + { + return typeof (DataTable); // nested datatable + } Type arrayType = GetColumnDataType(reader); return arrayType.MakeArrayType(); @@ -208,7 +228,9 @@ namespace Newtonsoft.Json.Converters private static void CheckedRead(JsonReader reader) { if (!reader.Read()) + { throw JsonSerializationException.Create(reader, "Unexpected end when reading DataTable."); + } } ///