-Added GetValue and TryGetValue with StringComparison to JObject

-Fixed SecAnnotate warnings
-Fixed error when comparing empty JObjects
-Fixed error when comparing DateTime JValue with a DateTimeOffset JValue
This commit is contained in:
James Newton-King
2012-09-13 22:49:35 +12:00
parent 9821483bf0
commit efc946d8df
9 changed files with 227 additions and 59 deletions
+40 -13
View File
@@ -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);
}
}
@@ -1865,5 +1865,52 @@ Parameter name: arrayIndex",
l2 = o.ToList<KeyValuePair<string, JToken>>();
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));
}
}
}
+59 -38
View File
@@ -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<InvalidOperationException>("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<InvalidOperationException>("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<InvalidOperationException>("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<InvalidOperationException>("Cannot access child value on Newtonsoft.Json.Linq.JValue.",
() =>
{
JValue v = new JValue(true);
v.Values<int>();
});
() =>
{
JValue v = new JValue(true);
v.Values<int>();
});
}
[Test]
public void RemoveParentNull()
{
ExceptionAssert.Throws<InvalidOperationException>("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<InvalidOperationException>("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<ArgumentException>("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
}
}
@@ -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
+53
View File
@@ -378,6 +378,59 @@ namespace Newtonsoft.Json.Linq
writer.WriteEndObject();
}
/// <summary>
/// Gets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
/// </summary>
/// <value>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</value>
public JToken GetValue(string propertyName)
{
return GetValue(propertyName, StringComparison.Ordinal);
}
/// <summary>
/// Gets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
/// The exact property name will be searched for first and if no matching property is found then
/// the <see cref="StringComparison"/> will be used to match a property.
/// </summary>
/// <value>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</value>
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;
}
/// <summary>
/// Tries to get the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
/// The exact property name will be searched for first and if no matching property is found then
/// the <see cref="StringComparison"/> will be used to match a property.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <param name="value">The value.</param>
/// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param>
/// <returns>true if a value was successfully retrieved; otherwise, false.</returns>
public bool TryGetValue(string propertyName, StringComparison comparison, out JToken value)
{
value = GetValue(propertyName, comparison);
return (value != null);
}
#region IDictionary<string,JToken> Members
/// <summary>
/// Adds the specified property name.
@@ -200,6 +200,15 @@ namespace Newtonsoft.Json.Linq
Dictionary<string, JToken> d1 = _dictionary;
Dictionary<string, JToken> 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;
+13 -6
View File
@@ -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);
}
@@ -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)]
@@ -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)