// JsonHelper.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
public static class JsonHelper
{
/// <summary>
/// 对JSON属性进行升序排序
/// </summary>
public static JToken GetSortedObject(JToken obj)
{
if (obj is JArray jArray)
{
var jArray2 = new JArray();
foreach (var item in jArray)
{
jArray2.Add(GetSortedObject(item));
}
return jArray2;
}
else if (obj is JObject jObject)
{
var sortedDic = new SortedDictionary<string, JToken>();
foreach (var jProperty in jObject.Properties())
{
if (jProperty.Value is JArray || jProperty.Value is JObject)
{
sortedDic.Add(jProperty.Name, GetSortedObject(jProperty.Value));
}
else
{
sortedDic.Add(jProperty.Name, jProperty.Value);
}
}
var newJObject = new JObject();
foreach ((var key, var value) in sortedDic)
{
newJObject.Add(key, value);
}
return newJObject;
}
else
{
return obj;
}
}
}
比较实现代码
cs复制代码
// JsonHelper.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
public static class JsonHelper
{
public static bool JValueEquals(JToken? obj1, JToken? obj2)
{
if (obj1 is JArray jArray && obj2 is JArray jArray2)
{
var jarr2_items = jArray2.ToList();
foreach (var item1 in jArray)
{
var item2 = jarr2_items.PickItem(x => JValueEquals(item1, x));
if (item2 is null)
{
return false;
}
}
return true;
}
else if (obj1 is JObject jObject && obj2 is JObject jObject2)
{
var j2_props = jObject2.Properties().ToList();
foreach (var p1 in jObject.Properties())
{
var p2 = j2_props.FirstOrDefault(x => x.Name == p1.Name);
if (p2 is null || !JValueEquals(p1.Value, p2.Value))
{
return false;
}
}
return true;
}
else if (obj1 is JValue v1 && obj2 is JValue v2)
{
if ((v1.Type == JTokenType.Float && (v2.Type == JTokenType.Float || v2.Type == JTokenType.Integer))
|| v2.Type == JTokenType.Float && v1.Type == JTokenType.Integer)
{
if (v1.Value == v2.Value)
{
return true;
}
if (v1.Value == null || v2.Value == null)
{
return false;
}
var d1 = v1.Type == JTokenType.Integer ? (long)v1.Value : (double)v1.Value;
var d2 = v2.Type == JTokenType.Integer ? (long)v2.Value : (double)v2.Value;
return DoubleEqual(d1, d2);
}
if (v1.Type == JTokenType.Integer && v2.Type == JTokenType.Integer)
{
if (v1.Value == v2.Value)
{
return true;
}
if (v1.Value == null || v2.Value == null)
{
return false;
}
return (long)v1.Value == (long)v2.Value;
}
return Object.Equals(v1.Value, v2.Value);
}
return Object.Equals(obj1, obj2);
}
/// <summary>
/// 浮点数相等
/// </summary>
/// <param name="d"></param>
/// <param name="d2"></param>
/// <returns></returns>
public static bool DoubleEqual(double? d, double? d2)
{
// https://learn.microsoft.com/zh-cn/dotnet/api/system.double.epsilon?view=net-7.0
// ReSharper disable once CompareOfFloatsByEqualityOperator
return d == d2 || (d.HasValue && d2.HasValue && Math.Abs(d.Value - d2.Value) < (2.2250738585072014E-308));
}
}
// IListExtension.cs
using System.Collections.ObjectModel;
public static class IListExtension
{
public static T? PickItem<T>(this IList<T> list, Predicate<T> predicate)
{
T data;
for (int i = 0; i < list.Count; i++)
{
if (predicate(list[i]))
{
data = list[i];
list.RemoveAt(i);
return data;
}
}
return default(T?);
}
}