-Added ICloneable and DeepClone to JToken
-Changed DeepEquals to take into account possible floating point errors
This commit is contained in:
@@ -646,5 +646,81 @@ namespace Newtonsoft.Json.Tests.Linq
|
||||
Assert.AreEqual("secondlastpie", (string)a[5]);
|
||||
Assert.AreEqual(7, a.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeepClone()
|
||||
{
|
||||
JArray a =
|
||||
new JArray(
|
||||
5,
|
||||
new JArray(1),
|
||||
new JArray(1, 2),
|
||||
new JArray(1, 2, 3),
|
||||
new JObject(
|
||||
new JProperty("First", new JValue(Encoding.UTF8.GetBytes("Hi"))),
|
||||
new JProperty("Second", 1),
|
||||
new JProperty("Third", null),
|
||||
new JProperty("Fourth", new JConstructor("Date", 12345)),
|
||||
new JProperty("Fifth", double.PositiveInfinity),
|
||||
new JProperty("Sixth", double.NaN)
|
||||
)
|
||||
);
|
||||
|
||||
JArray a2 = (JArray)a.DeepClone();
|
||||
|
||||
Console.WriteLine(a2.ToString(Formatting.Indented));
|
||||
|
||||
Assert.IsTrue(a.DeepEquals(a2));
|
||||
}
|
||||
|
||||
#if !SILVERLIGHT
|
||||
[Test]
|
||||
public void Clone()
|
||||
{
|
||||
JArray a =
|
||||
new JArray(
|
||||
5,
|
||||
new JArray(1),
|
||||
new JArray(1, 2),
|
||||
new JArray(1, 2, 3),
|
||||
new JObject(
|
||||
new JProperty("First", new JValue(Encoding.UTF8.GetBytes("Hi"))),
|
||||
new JProperty("Second", 1),
|
||||
new JProperty("Third", null),
|
||||
new JProperty("Fourth", new JConstructor("Date", 12345)),
|
||||
new JProperty("Fifth", double.PositiveInfinity),
|
||||
new JProperty("Sixth", double.NaN)
|
||||
)
|
||||
);
|
||||
|
||||
ICloneable c = a;
|
||||
|
||||
JArray a2 = (JArray) c.Clone();
|
||||
|
||||
Assert.IsTrue(a.DeepEquals(a2));
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void DoubleDeepEquals()
|
||||
{
|
||||
JArray a =
|
||||
new JArray(
|
||||
double.NaN,
|
||||
double.PositiveInfinity,
|
||||
double.NegativeInfinity
|
||||
);
|
||||
|
||||
JArray a2 = (JArray)a.DeepClone();
|
||||
|
||||
Assert.IsTrue(a.DeepEquals(a2));
|
||||
|
||||
double d = 1 + 0.1 + 0.1 + 0.1;
|
||||
|
||||
JValue v1 = new JValue(d);
|
||||
JValue v2 = new JValue(1.3);
|
||||
|
||||
Assert.IsTrue(v1.DeepEquals(v2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,13 @@ namespace Newtonsoft.Json.Linq
|
||||
/// Represents an abstract JSON token.
|
||||
/// </summary>
|
||||
public abstract class JToken : IJEnumerable<JToken>, IJsonLineInfo
|
||||
#if !(NET35 || NET20 || SILVERLIGHT)
|
||||
, IDynamicMetaObjectProvider
|
||||
#if !SILVERLIGHT
|
||||
, ICloneable
|
||||
#endif
|
||||
{
|
||||
#if !(NET35 || NET20 || SILVERLIGHT)
|
||||
, IDynamicMetaObjectProvider
|
||||
#endif
|
||||
{
|
||||
private JContainer _parent;
|
||||
internal JToken _next;
|
||||
private static JTokenEqualityComparer _equalityComparer;
|
||||
@@ -1298,5 +1301,21 @@ namespace Newtonsoft.Json.Linq
|
||||
return GetMetaObject(parameter);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SILVERLIGHT
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return DeepClone();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="JToken"/>. All child tokens are recursively cloned.
|
||||
/// </summary>
|
||||
/// <returns>A new instance of the <see cref="JToken"/>.</returns>
|
||||
public JToken DeepClone()
|
||||
{
|
||||
return CloneToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,7 +159,13 @@ namespace Newtonsoft.Json.Linq
|
||||
else
|
||||
return Convert.ToInt64(objA, CultureInfo.InvariantCulture).Equals(Convert.ToInt64(objB, CultureInfo.InvariantCulture));
|
||||
case JTokenType.Float:
|
||||
return Convert.ToDouble(objA, CultureInfo.InvariantCulture).Equals(Convert.ToDouble(objB, CultureInfo.InvariantCulture));
|
||||
double d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture);
|
||||
double d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture);
|
||||
if (d1.Equals(d2))
|
||||
return true;
|
||||
|
||||
// take into account possible floating point errors
|
||||
return MathUtils.ApproxEquals(d1, d2);
|
||||
case JTokenType.Comment:
|
||||
case JTokenType.String:
|
||||
case JTokenType.Boolean:
|
||||
|
||||
@@ -124,5 +124,11 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
return Math.Max(val1.Value, val2.Value);
|
||||
}
|
||||
|
||||
public static bool ApproxEquals(double d1, double d2)
|
||||
{
|
||||
// are values equal to within 12 (or so) digits of precision?
|
||||
return Math.Abs(d1 - d2) < (Math.Abs(d1) * 1e-12);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user