-Added EqualityComparer to JsonSerializer
This commit is contained in:
@@ -798,6 +798,9 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
serializer.Culture = new CultureInfo("en-nz");
|
||||
Assert.AreEqual("en-NZ", serializer.Culture.ToString());
|
||||
|
||||
serializer.EqualityComparer = EqualityComparer<object>.Default;
|
||||
Assert.AreEqual(EqualityComparer<object>.Default, serializer.EqualityComparer);
|
||||
|
||||
serializer.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
|
||||
Assert.AreEqual(DateFormatHandling.MicrosoftDateFormat, serializer.DateFormatHandling);
|
||||
|
||||
@@ -890,6 +893,9 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
settings.Culture = new CultureInfo("en-nz");
|
||||
Assert.AreEqual("en-NZ", settings.Culture.ToString());
|
||||
|
||||
settings.EqualityComparer = EqualityComparer<object>.Default;
|
||||
Assert.AreEqual(EqualityComparer<object>.Default, settings.EqualityComparer);
|
||||
|
||||
settings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
|
||||
Assert.AreEqual(DateFormatHandling.MicrosoftDateFormat, settings.DateFormatHandling);
|
||||
|
||||
@@ -988,6 +994,9 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
serializerProxy.Culture = new CultureInfo("en-nz");
|
||||
Assert.AreEqual("en-NZ", serializerProxy.Culture.ToString());
|
||||
|
||||
serializerProxy.EqualityComparer = EqualityComparer<object>.Default;
|
||||
Assert.AreEqual(EqualityComparer<object>.Default, serializerProxy.EqualityComparer);
|
||||
|
||||
serializerProxy.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
|
||||
Assert.AreEqual(DateFormatHandling.MicrosoftDateFormat, serializerProxy.DateFormatHandling);
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
#if NETFX_CORE
|
||||
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
|
||||
using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
|
||||
@@ -268,6 +270,80 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
Assert.AreEqual(@"{""child"":{""name"":""child""},""name"":""parent""}", c);
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void EqualityComparer()
|
||||
{
|
||||
AccountWithEquals account = new AccountWithEquals
|
||||
{
|
||||
Name = "main"
|
||||
};
|
||||
AccountWithEquals manager = new AccountWithEquals
|
||||
{
|
||||
Name = "main"
|
||||
};
|
||||
account.Manager = manager;
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(
|
||||
() => JsonConvert.SerializeObject(account),
|
||||
"Self referencing loop detected for property 'Manager' with type 'Newtonsoft.Json.Tests.Serialization.AccountWithEquals'. Path ''.");
|
||||
|
||||
string json = JsonConvert.SerializeObject(account, new JsonSerializerSettings
|
||||
{
|
||||
EqualityComparer = new ReferenceEqualsEqualityComparer(),
|
||||
Formatting = Formatting.Indented
|
||||
});
|
||||
|
||||
StringAssert.AreEqual(@"{
|
||||
""Name"": ""main"",
|
||||
""Manager"": {
|
||||
""Name"": ""main"",
|
||||
""Manager"": null
|
||||
}
|
||||
}", json);
|
||||
}
|
||||
}
|
||||
|
||||
public class ReferenceEqualsEqualityComparer : IEqualityComparer
|
||||
{
|
||||
bool IEqualityComparer.Equals(object x, object y)
|
||||
{
|
||||
return ReferenceEquals(x, y);
|
||||
}
|
||||
|
||||
int IEqualityComparer.GetHashCode(object obj)
|
||||
{
|
||||
#if !(NETFX_CORE)
|
||||
// put objects in a bucket based on their reference
|
||||
return RuntimeHelpers.GetHashCode(obj);
|
||||
#else
|
||||
// put all objects in the same bucket so ReferenceEquals is called on all
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public class AccountWithEquals
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public AccountWithEquals Manager { get; set; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
AccountWithEquals a = obj as AccountWithEquals;
|
||||
if (a == null)
|
||||
return false;
|
||||
|
||||
return Name == a.Name;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (Name == null)
|
||||
return 0;
|
||||
|
||||
return Name.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyItemReferenceLoopHandling
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
@@ -56,6 +57,7 @@ namespace Newtonsoft.Json
|
||||
internal JsonConverterCollection _converters;
|
||||
internal IContractResolver _contractResolver;
|
||||
internal ITraceWriter _traceWriter;
|
||||
internal IEqualityComparer _equalityComparer;
|
||||
internal SerializationBinder _binder;
|
||||
internal StreamingContext _context;
|
||||
private IReferenceResolver _referenceResolver;
|
||||
@@ -119,6 +121,16 @@ namespace Newtonsoft.Json
|
||||
set { _traceWriter = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the equality comparer used by the serializer when comparing references.
|
||||
/// </summary>
|
||||
/// <value>The equality comparer.</value>
|
||||
public virtual IEqualityComparer EqualityComparer
|
||||
{
|
||||
get { return _equalityComparer; }
|
||||
set { _equalityComparer = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets how type name writing and reading is handled by the serializer.
|
||||
/// </summary>
|
||||
@@ -563,6 +575,8 @@ namespace Newtonsoft.Json
|
||||
serializer.ReferenceResolver = settings.ReferenceResolverProvider();
|
||||
if (settings.TraceWriter != null)
|
||||
serializer.TraceWriter = settings.TraceWriter;
|
||||
if (settings.EqualityComparer != null)
|
||||
serializer.EqualityComparer = settings.EqualityComparer;
|
||||
if (settings.Binder != null)
|
||||
serializer.Binder = settings.Binder;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
@@ -199,6 +200,12 @@ namespace Newtonsoft.Json
|
||||
/// <value>The contract resolver.</value>
|
||||
public IContractResolver ContractResolver { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the equality comparer used by the serializer when comparing references.
|
||||
/// </summary>
|
||||
/// <value>The equality comparer.</value>
|
||||
public IEqualityComparer EqualityComparer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IReferenceResolver"/> used by the serializer when resolving references.
|
||||
/// </summary>
|
||||
|
||||
@@ -47,8 +47,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
// put objects in a bucket based on their reference
|
||||
return RuntimeHelpers.GetHashCode(obj);
|
||||
#else
|
||||
// put all objects in the same bucket so ReferenceEquals is called on all
|
||||
return -1;
|
||||
// put all objects in the same bucket so ReferenceEquals is called on all
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +272,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (referenceLoopHandling == null && containerContract != null)
|
||||
referenceLoopHandling = containerContract.ItemReferenceLoopHandling;
|
||||
|
||||
if (_serializeStack.IndexOf(value) != -1)
|
||||
bool exists = (Serializer._equalityComparer != null)
|
||||
? _serializeStack.Contains(value, Serializer._equalityComparer)
|
||||
: _serializeStack.Contains(value);
|
||||
|
||||
if (exists)
|
||||
{
|
||||
string message = "Self referencing loop detected";
|
||||
if (property != null)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
@@ -55,6 +56,12 @@ namespace Newtonsoft.Json.Serialization
|
||||
set { _serializer.TraceWriter = value; }
|
||||
}
|
||||
|
||||
public override IEqualityComparer EqualityComparer
|
||||
{
|
||||
get { return _serializer.EqualityComparer; }
|
||||
set { _serializer.EqualityComparer = value; }
|
||||
}
|
||||
|
||||
public override JsonConverterCollection Converters
|
||||
{
|
||||
get { return _serializer.Converters; }
|
||||
|
||||
@@ -190,8 +190,20 @@ namespace Newtonsoft.Json.Utilities
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static bool Contains(this IEnumerable list, object value, IEqualityComparer comparer)
|
||||
{
|
||||
foreach (object item in list)
|
||||
{
|
||||
if (comparer.Equals(item, value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer.
|
||||
/// Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer{TSource}.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
|
||||
/// <param name="list">A sequence in which to locate a value.</param>
|
||||
|
||||
Reference in New Issue
Block a user