diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs index aa4e2232..c081a719 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTest.cs @@ -2533,24 +2533,51 @@ bye", reader.Value); //Assert.IsFalse(jsonTextReader.Read()); } - public class ToggleReaderError : TextReader + [Test] + public void WriteReadBoundaryDecimals() { - private readonly TextReader _inner; + StringWriter sw = new StringWriter(); + JsonTextWriter writer = new JsonTextWriter(sw); - public bool Error { get; set; } + writer.WriteStartArray(); + writer.WriteValue(decimal.MaxValue); + writer.WriteValue(decimal.MinValue); + writer.WriteEndArray(); - public ToggleReaderError(TextReader inner) - { - _inner = inner; - } + string json = sw.ToString(); - public override int Read(char[] buffer, int index, int count) - { - if (Error) - throw new Exception("Read error"); + StringReader sr = new StringReader(json); + JsonTextReader reader = new JsonTextReader(sr); - return _inner.Read(buffer, index, 1); - } + Assert.IsTrue(reader.Read()); + + decimal? max = reader.ReadAsDecimal(); + Assert.AreEqual(decimal.MaxValue, max); + + decimal? min = reader.ReadAsDecimal(); + Assert.AreEqual(decimal.MinValue, min); + + Assert.IsTrue(reader.Read()); + } + } + + public class ToggleReaderError : TextReader + { + private readonly TextReader _inner; + + public bool Error { get; set; } + + public ToggleReaderError(TextReader inner) + { + _inner = inner; + } + + public override int Read(char[] buffer, int index, int count) + { + if (Error) + throw new Exception("Read error"); + + return _inner.Read(buffer, index, 1); } } diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index 2f3ce3b9..704faf76 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -1865,5 +1865,52 @@ Parameter name: arrayIndex", l2 = o.ToList>(); Assert.AreEqual(1, l2.Count); } + + [Test] + public void EmptyObjectDeepEquals() + { + Assert.IsTrue(JToken.DeepEquals(new JObject(), new JObject())); + + JObject a = new JObject(); + JObject b = new JObject(); + + b.Add("hi", "bye"); + b.Remove("hi"); + + Assert.IsTrue(JToken.DeepEquals(a, b)); + Assert.IsTrue(JToken.DeepEquals(b, a)); + } + + [Test] + public void GetValue() + { + JObject a = new JObject(); + a["Name"] = "Name!"; + a["name"] = "name!"; + a["title"] = "Title!"; + + Assert.AreEqual(null, a.GetValue("NAME", StringComparison.Ordinal)); + Assert.AreEqual(null, a.GetValue("NAME")); + Assert.AreEqual(null, a.GetValue("TITLE")); + Assert.AreEqual("Name!", (string)a.GetValue("NAME", StringComparison.OrdinalIgnoreCase)); + Assert.AreEqual("name!", (string)a.GetValue("name", StringComparison.Ordinal)); + Assert.AreEqual(null, a.GetValue(null, StringComparison.Ordinal)); + Assert.AreEqual(null, a.GetValue(null)); + + JToken v; + Assert.IsFalse(a.TryGetValue("NAME", StringComparison.Ordinal, out v)); + Assert.AreEqual(null, v); + + Assert.IsFalse(a.TryGetValue("NAME", out v)); + Assert.IsFalse(a.TryGetValue("TITLE", out v)); + + Assert.IsTrue(a.TryGetValue("NAME", StringComparison.OrdinalIgnoreCase, out v)); + Assert.AreEqual("Name!", (string)v); + + Assert.IsTrue(a.TryGetValue("name", StringComparison.Ordinal, out v)); + Assert.AreEqual("name!", (string)v); + + Assert.IsFalse(a.TryGetValue(null, StringComparison.Ordinal, out v)); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs index 6bc6c6eb..a4c88862 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs @@ -61,7 +61,7 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(null, v.Value); Assert.AreEqual(JTokenType.Null, v.Type); - v.Value = (int?)null; + v.Value = (int?) null; Assert.AreEqual(null, v.Value); Assert.AreEqual(JTokenType.Null, v.Type); @@ -156,11 +156,11 @@ namespace Newtonsoft.Json.Tests.Linq public void Last() { ExceptionAssert.Throws("Cannot access child value on Newtonsoft.Json.Linq.JValue.", - () => - { - JValue v = new JValue(true); - JToken last = v.Last; - }); + () => + { + JValue v = new JValue(true); + JToken last = v.Last; + }); } [Test] @@ -175,44 +175,44 @@ namespace Newtonsoft.Json.Tests.Linq public void First() { ExceptionAssert.Throws("Cannot access child value on Newtonsoft.Json.Linq.JValue.", - () => - { - JValue v = new JValue(true); - JToken first = v.First; - }); + () => + { + JValue v = new JValue(true); + JToken first = v.First; + }); } [Test] public void Item() { ExceptionAssert.Throws("Cannot access child value on Newtonsoft.Json.Linq.JValue.", - () => - { - JValue v = new JValue(true); - JToken first = v[0]; - }); + () => + { + JValue v = new JValue(true); + JToken first = v[0]; + }); } [Test] public void Values() { ExceptionAssert.Throws("Cannot access child value on Newtonsoft.Json.Linq.JValue.", - () => - { - JValue v = new JValue(true); - v.Values(); - }); + () => + { + JValue v = new JValue(true); + v.Values(); + }); } [Test] public void RemoveParentNull() { ExceptionAssert.Throws("The parent is missing.", - () => - { - JValue v = new JValue(true); - v.Remove(); - }); + () => + { + JValue v = new JValue(true); + v.Remove(); + }); } [Test] @@ -241,7 +241,7 @@ namespace Newtonsoft.Json.Tests.Linq { Assert.IsTrue(JToken.DeepEquals(new JValue(5L), new JValue(5))); Assert.IsFalse(JToken.DeepEquals(new JValue(5M), new JValue(5))); - Assert.IsTrue(JToken.DeepEquals(new JValue((ulong)long.MaxValue), new JValue(long.MaxValue))); + Assert.IsTrue(JToken.DeepEquals(new JValue((ulong) long.MaxValue), new JValue(long.MaxValue))); } [Test] @@ -254,22 +254,22 @@ namespace Newtonsoft.Json.Tests.Linq public void SetValue() { ExceptionAssert.Throws("Cannot set child value on Newtonsoft.Json.Linq.JValue.", - () => - { - JToken t = new JValue(5L); - t[0] = new JValue(3); - }); + () => + { + JToken t = new JValue(5L); + t[0] = new JValue(3); + }); } [Test] public void CastNullValueToNonNullable() { ExceptionAssert.Throws("Can not convert Null to Int32.", - () => - { - JValue v = new JValue((object)null); - int i = (int)v; - }); + () => + { + JValue v = new JValue((object) null); + int i = (int) v; + }); } [Test] @@ -320,7 +320,7 @@ namespace Newtonsoft.Json.Tests.Linq public decimal Compoundings { get; set; } } - private readonly Rate rate = new Rate { Compoundings = 12.166666666666666666666666667m }; + private readonly Rate rate = new Rate {Compoundings = 12.166666666666666666666666667m}; [Test] public void WriteFullDecimalPrecision() @@ -342,5 +342,26 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(rate.Compoundings, rate2.Compoundings); } + +#if !NET20 + public class ObjectWithDateTimeOffset + { + public DateTimeOffset DateTimeOffset { get; set; } + } + + [Test] + public void SetDateTimeOffsetProperty() + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2000, 1, 1), TimeSpan.FromHours(3)); + var json = JsonConvert.SerializeObject( + new ObjectWithDateTimeOffset + { + DateTimeOffset = dateTimeOffset + }); + + var o = JObject.Parse(json); + o.Property("DateTimeOffset").Value = dateTimeOffset; + } +#endif } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index aaa28c86..1b5c059e 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -76,5 +76,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.9.15307")] +[assembly: AssemblyFileVersion("4.5.9.15313")] #endif diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 8719aadf..531f824b 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -378,6 +378,59 @@ namespace Newtonsoft.Json.Linq writer.WriteEndObject(); } + /// + /// Gets the with the specified property name. + /// + /// The with the specified property name. + public JToken GetValue(string propertyName) + { + return GetValue(propertyName, StringComparison.Ordinal); + } + + /// + /// Gets the with the specified property name. + /// The exact property name will be searched for first and if no matching property is found then + /// the will be used to match a property. + /// + /// The with the specified property name. + public JToken GetValue(string propertyName, StringComparison comparison) + { + if (propertyName == null) + return null; + + // attempt to get value via dictionary first for performance + JProperty property = Property(propertyName); + if (property != null) + return property.Value; + + // test above already uses this comparison so no need to repeat + if (comparison != StringComparison.Ordinal) + { + foreach (JProperty p in _properties) + { + if (string.Equals(p.Name, propertyName, comparison)) + return p.Value; + } + } + + return null; + } + + /// + /// Tries to get the with the specified property name. + /// The exact property name will be searched for first and if no matching property is found then + /// the will be used to match a property. + /// + /// Name of the property. + /// The value. + /// One of the enumeration values that specifies how the strings will be compared. + /// true if a value was successfully retrieved; otherwise, false. + public bool TryGetValue(string propertyName, StringComparison comparison, out JToken value) + { + value = GetValue(propertyName, comparison); + return (value != null); + } + #region IDictionary Members /// /// Adds the specified property name. diff --git a/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs b/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs index e0c91cb0..aa063c88 100644 --- a/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs +++ b/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs @@ -200,6 +200,15 @@ namespace Newtonsoft.Json.Linq Dictionary d1 = _dictionary; Dictionary d2 = other._dictionary; + if (d1 == null && d2 == null) + return true; + + if (d1 == null) + return (d2.Count == 0); + + if (d2 == null) + return (d1.Count == 0); + if (d1.Count != d2.Count) return false; diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 5fd95037..5742e3d9 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -216,19 +216,26 @@ namespace Newtonsoft.Json.Linq if (objA is DateTime) { #endif - DateTime date1 = Convert.ToDateTime(objA, CultureInfo.InvariantCulture); - DateTime date2 = Convert.ToDateTime(objB, CultureInfo.InvariantCulture); + DateTime date1 = (DateTime)objA; + DateTime date2; + + if (objB is DateTimeOffset) + date2 = ((DateTimeOffset)objB).DateTime; + else + date2 = Convert.ToDateTime(objB, CultureInfo.InvariantCulture); return date1.CompareTo(date2); #if !NET20 } else { - if (!(objB is DateTimeOffset)) - throw new ArgumentException("Object must be of type DateTimeOffset."); - DateTimeOffset date1 = (DateTimeOffset) objA; - DateTimeOffset date2 = (DateTimeOffset) objB; + DateTimeOffset date2; + + if (objB is DateTimeOffset) + date2 = (DateTimeOffset)objB; + else + date2 = new DateTimeOffset(Convert.ToDateTime(objB, CultureInfo.InvariantCulture)); return date1.CompareTo(date2); } diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 2696467b..afd5f6cd 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -90,7 +90,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.9.15307")] +[assembly: AssemblyFileVersion("4.5.9.15313")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 795db900..31259f22 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -27,6 +27,7 @@ using System; using System.ComponentModel; using System.Globalization; using System.Reflection; +using System.Security; #if !(NETFX_CORE || PORTABLE) using System.Security.Permissions; #endif @@ -388,6 +389,9 @@ namespace Newtonsoft.Json.Serialization public static bool DynamicCodeGeneration { +#if !(NET20 || NET35 || SILVERLIGHT || NETFX_CORE || PORTABLE) + [SecuritySafeCritical] +#endif get { if (_dynamicCodeGeneration == null)