From c987b0509a49826a557b9f8f20f490f1acc28bd2 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Jun 2014 15:04:17 +1200 Subject: [PATCH] -Fixed JsonConvert.PopulateObject not setting JsonReader settings --- Src/Newtonsoft.Json.Tests/JsonConvertTest.cs | 22 +++ .../Serialization/JsonSerializerTest.cs | 20 +++ .../Serialization/TraceWriterTests.cs | 60 ++++++++ Src/Newtonsoft.Json/JsonSerializer.cs | 142 ++++++++++++------ 4 files changed, 198 insertions(+), 46 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs index b6caf537..9ad0f186 100644 --- a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs @@ -998,6 +998,28 @@ now brown cow?", '"', true); Assert.AreEqual("Bad Boys", m.Name); } +#if !NET20 + [Test] + public void TestJsonDateTimeOffsetRoundtrip() + { + var now = DateTimeOffset.Now; + var dict = new Dictionary { { "foo", now } }; + + var settings = new JsonSerializerSettings(); + settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; + settings.DateParseHandling = DateParseHandling.DateTimeOffset; + settings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; + var json = JsonConvert.SerializeObject(dict, settings); + + var newDict = new Dictionary(); + JsonConvert.PopulateObject(json, newDict, settings); + + var date = newDict["foo"]; + + Assert.AreEqual(date, now); + } +#endif + #if !(NET20 || NET35 || PORTABLE40 || PORTABLE) [Test] public void IntegerLengthOverflows() diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index eddf7607..83c9ec44 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -91,6 +91,26 @@ namespace Newtonsoft.Json.Tests.Serialization [TestFixture] public class JsonSerializerTest : TestFixtureBase { +#if !NET20 + [Test] + public void PopulateResetSettings() + { + JsonTextReader reader = new JsonTextReader(new StringReader(@"[""2000-01-01T01:01:01+00:00""]")); + Assert.AreEqual(DateParseHandling.DateTime, reader.DateParseHandling); + + JsonSerializer serializer = new JsonSerializer(); + serializer.DateParseHandling = DateParseHandling.DateTimeOffset; + + IList l = new List(); + serializer.Populate(reader, l); + + Assert.AreEqual(typeof(DateTimeOffset), l[0].GetType()); + Assert.AreEqual(new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero), l[0]); + + Assert.AreEqual(DateParseHandling.DateTime, reader.DateParseHandling); + } +#endif + public class BaseClass { internal bool IsTransient { get; set; } diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs index 1d4bc2ed..278c76c5 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs @@ -289,6 +289,66 @@ Newtonsoft.Json Error: 0 : Error! Assert.IsFalse(traceWriter.TraceRecords.Any(r => r.Level == TraceLevel.Verbose)); } + [Test] + public void Populate() + { + InMemoryTraceWriter traceWriter = new InMemoryTraceWriter + { + LevelFilter = TraceLevel.Info + }; + + TraceTestObject o2 = new TraceTestObject(); + + JsonConvert.PopulateObject(@"{ + ""IntList"": [ + 1, + 2 + ], + ""StringArray"": [ + ""1"", + ""2"" + ], + ""Version"": { + ""Major"": 1, + ""Minor"": 2, + ""Build"": 3, + ""Revision"": 4, + ""MajorRevision"": 0, + ""MinorRevision"": 4 + }, + ""StringDictionary"": { + ""1"": ""!"", + ""Two"": ""!!"", + ""III"": ""!!!"" + } +}", + o2, + new JsonSerializerSettings + { + TraceWriter = traceWriter + }); + + Assert.AreEqual(2, o2.IntList.Count); + Assert.AreEqual(2, o2.StringArray.Length); + Assert.AreEqual(1, o2.Version.Major); + Assert.AreEqual(2, o2.Version.Minor); + Assert.AreEqual(3, o2.StringDictionary.Count); + + Assert.AreEqual("Started deserializing Newtonsoft.Json.Tests.Serialization.TraceTestObject. Path 'IntList', line 2, position 13.", traceWriter.TraceRecords[0].Message); + Assert.AreEqual("Started deserializing System.Collections.Generic.IList`1[System.Int32]. Path 'IntList', line 2, position 15.", traceWriter.TraceRecords[1].Message); + Assert.IsTrue(traceWriter.TraceRecords[2].Message.StartsWith("Finished deserializing System.Collections.Generic.IList`1[System.Int32]. Path 'IntList'")); + Assert.AreEqual("Started deserializing System.String[]. Path 'StringArray', line 6, position 19.", traceWriter.TraceRecords[3].Message); + Assert.IsTrue(traceWriter.TraceRecords[4].Message.StartsWith("Finished deserializing System.String[]. Path 'StringArray'")); + Assert.AreEqual("Deserializing System.Version using creator with parameters: Major, Minor, Build, Revision. Path 'Version.Major', line 11, position 13.", traceWriter.TraceRecords[5].Message); + Assert.IsTrue(traceWriter.TraceRecords[6].Message.StartsWith("Started deserializing System.Version. Path 'Version'")); + Assert.IsTrue(traceWriter.TraceRecords[7].Message.StartsWith("Finished deserializing System.Version. Path 'Version'")); + Assert.AreEqual("Started deserializing System.Collections.Generic.IDictionary`2[System.String,System.String]. Path 'StringDictionary.1', line 19, position 9.", traceWriter.TraceRecords[8].Message); + Assert.IsTrue(traceWriter.TraceRecords[9].Message.StartsWith("Finished deserializing System.Collections.Generic.IDictionary`2[System.String,System.String]. Path 'StringDictionary'")); + Assert.IsTrue(traceWriter.TraceRecords[10].Message.StartsWith("Finished deserializing Newtonsoft.Json.Tests.Serialization.TraceTestObject. Path ''")); + + Assert.IsFalse(traceWriter.TraceRecords.Any(r => r.Level == TraceLevel.Verbose)); + } + [Test] public void ErrorDeserializing() { diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index c096595d..e5d37583 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -43,7 +43,6 @@ namespace Newtonsoft.Json /// public class JsonSerializer { - #region Properties_binder internal TypeNameHandling _typeNameHandling; internal FormatterAssemblyStyle _typeNameAssemblyFormat; internal PreserveReferencesHandling _preserveReferencesHandling; @@ -428,7 +427,6 @@ namespace Newtonsoft.Json { return (_checkAdditionalContent != null); } - #endregion /// /// Initializes a new instance of the class. @@ -623,8 +621,26 @@ namespace Newtonsoft.Json ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); + // set serialization options onto reader + CultureInfo previousCulture; + DateTimeZoneHandling? previousDateTimeZoneHandling; + DateParseHandling? previousDateParseHandling; + FloatParseHandling? previousFloatParseHandling; + int? previousMaxDepth; + string previousDateFormatString; + SetupReader(reader, out previousCulture, out previousDateTimeZoneHandling, out previousDateParseHandling, out previousFloatParseHandling, out previousMaxDepth, out previousDateFormatString); + + TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) + ? new TraceJsonReader(reader) + : null; + JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this); - serializerReader.Populate(reader, target); + serializerReader.Populate(traceJsonReader ?? reader, target); + + if (traceJsonReader != null) + TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null); + + ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } /// @@ -678,47 +694,13 @@ namespace Newtonsoft.Json ValidationUtils.ArgumentNotNull(reader, "reader"); // set serialization options onto reader - CultureInfo previousCulture = null; - if (_culture != null && !_culture.Equals(reader.Culture)) - { - previousCulture = reader.Culture; - reader.Culture = _culture; - } - - DateTimeZoneHandling? previousDateTimeZoneHandling = null; - if (_dateTimeZoneHandling != null && reader.DateTimeZoneHandling != _dateTimeZoneHandling) - { - previousDateTimeZoneHandling = reader.DateTimeZoneHandling; - reader.DateTimeZoneHandling = _dateTimeZoneHandling.Value; - } - - DateParseHandling? previousDateParseHandling = null; - if (_dateParseHandling != null && reader.DateParseHandling != _dateParseHandling) - { - previousDateParseHandling = reader.DateParseHandling; - reader.DateParseHandling = _dateParseHandling.Value; - } - - FloatParseHandling? previousFloatParseHandling = null; - if (_floatParseHandling != null && reader.FloatParseHandling != _floatParseHandling) - { - previousFloatParseHandling = reader.FloatParseHandling; - reader.FloatParseHandling = _floatParseHandling.Value; - } - - int? previousMaxDepth = null; - if (_maxDepthSet && reader.MaxDepth != _maxDepth) - { - previousMaxDepth = reader.MaxDepth; - reader.MaxDepth = _maxDepth; - } - - string previousDateFormatString = null; - if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) - { - previousDateFormatString = reader.DateFormatString; - reader.DateFormatString = _dateFormatString; - } + CultureInfo previousCulture; + DateTimeZoneHandling? previousDateTimeZoneHandling; + DateParseHandling? previousDateParseHandling; + FloatParseHandling? previousFloatParseHandling; + int? previousMaxDepth; + string previousDateFormatString; + SetupReader(reader, out previousCulture, out previousDateTimeZoneHandling, out previousDateParseHandling, out previousFloatParseHandling, out previousMaxDepth, out previousDateFormatString); TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonReader(reader) @@ -730,6 +712,76 @@ namespace Newtonsoft.Json if (traceJsonReader != null) TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null); + ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); + + return value; + } + + private void SetupReader(JsonReader reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString) + { + if (_culture != null && !_culture.Equals(reader.Culture)) + { + previousCulture = reader.Culture; + reader.Culture = _culture; + } + else + { + previousCulture = null; + } + + if (_dateTimeZoneHandling != null && reader.DateTimeZoneHandling != _dateTimeZoneHandling) + { + previousDateTimeZoneHandling = reader.DateTimeZoneHandling; + reader.DateTimeZoneHandling = _dateTimeZoneHandling.Value; + } + else + { + previousDateTimeZoneHandling = null; + } + + if (_dateParseHandling != null && reader.DateParseHandling != _dateParseHandling) + { + previousDateParseHandling = reader.DateParseHandling; + reader.DateParseHandling = _dateParseHandling.Value; + } + else + { + previousDateParseHandling = null; + } + + if (_floatParseHandling != null && reader.FloatParseHandling != _floatParseHandling) + { + previousFloatParseHandling = reader.FloatParseHandling; + reader.FloatParseHandling = _floatParseHandling.Value; + } + else + { + previousFloatParseHandling = null; + } + + if (_maxDepthSet && reader.MaxDepth != _maxDepth) + { + previousMaxDepth = reader.MaxDepth; + reader.MaxDepth = _maxDepth; + } + else + { + previousMaxDepth = null; + } + + if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) + { + previousDateFormatString = reader.DateFormatString; + reader.DateFormatString = _dateFormatString; + } + else + { + previousDateFormatString = null; + } + } + + private void ResetReader(JsonReader reader, CultureInfo previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string previousDateFormatString) + { // reset reader back to previous options if (previousCulture != null) reader.Culture = previousCulture; @@ -743,8 +795,6 @@ namespace Newtonsoft.Json reader.MaxDepth = previousMaxDepth; if (_dateFormatStringSet) reader.DateFormatString = previousDateFormatString; - - return value; } ///