Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 比较相同结构的两个任意JToken-s_C#_Json_Json.net - Fatal编程技术网

C# 比较相同结构的两个任意JToken-s

C# 比较相同结构的两个任意JToken-s,c#,json,json.net,C#,Json,Json.net,提前谢谢。谢谢你的帮助 我想比较两个相同类型和结构的任意jtoken(NewtonSoft的Json.Net) 主要目标是能够使用此方法对两个Json字符串进行排序,这样即使在开始时它们具有相同的数据,但顺序不同,最终它们也是两个完全相同的字符串。所以排序标准并不重要,重要的是这个标准总是一样的。每一小部分数据都应该考虑在内 JToken可以是以下几种类型之一:Array、Boolean、Date、Float、Guid、Integer、Null、Object、Property、String、Ti

提前谢谢。谢谢你的帮助

我想比较两个相同类型和结构的任意jtoken(NewtonSoft的Json.Net)

主要目标是能够使用此方法对两个Json字符串进行排序,这样即使在开始时它们具有相同的数据,但顺序不同,最终它们也是两个完全相同的字符串。所以排序标准并不重要,重要的是这个标准总是一样的。每一小部分数据都应该考虑在内

JToken可以是以下几种类型之一:
Array、Boolean、Date、Float、Guid、Integer、Null、Object、Property、String、TimeSpan、Uri
。我不考虑比较
字节、注释、构造函数、无、未定义、原始

  • 如果能了解一些比较Jarray和JObjects的方法,那就太好了。这应该是一些递归比较,因为Jarray可能由其他Jarray和Jobject组成,反之亦然。任何想法都将不胜感激
  • 但是了解比较简单类型也会很有帮助。我更想知道如何从JToken转换为实际类型(而不是知道如何逻辑地转换)
  • JValue已经实现了IComparable,但我没有弄清楚如何将简单类型的JToken转换为JValue。了解这一点也会有所帮助
这是一个相当棘手的问题。如果我知道怎么做,我会加上+100。对不起,我说的是英语。

在Linq to JSON中,表示一个基本值(字符串、数字、布尔值等)。它实现了,因此Json.NET负责为您排序原语值

在此基础上,您将需要并行递归地降低两个
JToken
对象层次结构。当您遇到具有不同.Net类型、不同属性(如果不是
JValue
)或具有不同值(如果是
JValue
)的第一个令牌时,您需要返回比较值

请记住以下几点:

  • 比较方法应该是自反的、反对称的和传递的
  • 不同.Net类型的容器令牌需要以某种一致的方式按类型排序
  • JArray
    JConstructor
    的子令牌已排序
  • JObject
    的子标记不是,因此需要以某种稳定、对称的方式对它们进行比较。按属性名称的顺序遍历这两个属性似乎是可行的
  • 没有明显的方法来比较
    JRaw
    ,所以不要尝试,让异常被抛出
以下是一个原型实现:

public class JTokenComparer : IComparer<JToken>
{
    public static JTokenComparer Instance { get { return instance; } }

    static JTokenComparer instance;

    static JTokenComparer()
    {
        instance = new JTokenComparer();
    }

    readonly Dictionary<Type, KeyValuePair<int, IComparer<JToken>>> dict;

    JTokenComparer()
    {
        dict = new Dictionary<Type, KeyValuePair<int, IComparer<JToken>>>
        {
            // Order chosen semi-arbitrarily.  Putting values first seems reasonable though.
            {typeof(JValue), new KeyValuePair<int, IComparer<JToken>>(0, new JValueComparer()) },
            {typeof(JProperty), new KeyValuePair<int, IComparer<JToken>>(1, new JPropertyComparer()) },
            {typeof(JArray), new KeyValuePair<int, IComparer<JToken>>(2, new JArrayComparer()) },
            {typeof(JObject), new KeyValuePair<int, IComparer<JToken>>(3, new JObjectComparer()) },
            {typeof(JConstructor), new KeyValuePair<int, IComparer<JToken>>(4, new JConstructorComparer()) },
        };
    }

    #region IComparer<JToken> Members

    public int Compare(JToken x, JToken y)
    {
        if (x is JRaw || y is JRaw)
            throw new InvalidOperationException("Tokens of type JRaw cannot be sorted");
        if (object.ReferenceEquals(x, y))
            return 0;
        else if (x == null)
            return -1;
        else if (y == null)
            return 1;

        var typeData1 = dict[x.GetType()];
        var typeData2 = dict[y.GetType()];

        int comp;
        if ((comp = typeData1.Key.CompareTo(typeData2.Key)) != 0)
            return comp;
        if (typeData1.Value != typeData2.Value)
            throw new InvalidOperationException("inconsistent dictionary values"); // Internal error
        return typeData2.Value.Compare(x, y);
    }

    #endregion
}

abstract class JTokenComparerBase<TJToken> : IComparer<JToken> where TJToken : JToken
{
    protected TJToken CheckType(JToken item)
    {
        if (item != null && item.GetType() != typeof(TJToken))
            throw new ArgumentException(string.Format("Actual type {0} of token \"{1}\" does not match expected type {2}", item.GetType(), item, typeof(TJToken)));
        return (TJToken)item;
    }

    protected bool TryBaseCompare(TJToken x, TJToken y, out int comparison)
    {
        CheckType(x);
        CheckType(y);
        if (object.ReferenceEquals(x, y))
        {
            comparison = 0;
            return true;
        }
        else if (x == null)
        {
            comparison = -1;
            return true;
        }
        else if (y == null)
        {
            comparison = 1;
            return true;
        }
        comparison = 0;
        return false;
    }

    protected abstract int CompareDerived(TJToken x, TJToken y);

    protected int TokenCompare(JToken x, JToken y)
    {
        var tx = CheckType(x);
        var ty = CheckType(y);
        int comp;
        if (TryBaseCompare(tx, ty, out comp))
            return comp;
        return CompareDerived(tx, ty);
    }

    #region IComparer<JToken> Members

    int IComparer<JToken>.Compare(JToken x, JToken y)
    {
        return TokenCompare(x, y);
    }

    #endregion
}

abstract class JContainerOrderedComparerBase<TJToken> : JTokenComparerBase<TJToken> where TJToken : JContainer
{
    protected int CompareItemsInOrder(TJToken x, TJToken y)
    {
        int comp;
        // Dictionary order: sort on items before number of items.
        for (int i = 0, n = Math.Min(x.Count, y.Count); i < n; i++)
            if ((comp = JTokenComparer.Instance.Compare(x[i], y[i])) != 0)
                return comp;
        if ((comp = x.Count.CompareTo(y.Count)) != 0)
            return comp;
        return 0;
    }
}

class JPropertyComparer : JTokenComparerBase<JProperty>
{
    protected override int CompareDerived(JProperty x, JProperty y)
    {
        int comp;
        if ((comp = x.Name.CompareTo(y.Name)) != 0)
            return comp;
        return JTokenComparer.Instance.Compare(x.Value, y.Value);
    }
}

class JObjectComparer : JTokenComparerBase<JObject>
{
    protected override int CompareDerived(JObject x, JObject y)
    {
        int comp;
        // Dictionary order: sort on items before number of items.
        // Order both property sequences to preserve reflexivity.
        foreach (var propertyComp in x.Properties().OrderBy(p => p.Name).Zip(y.Properties().OrderBy(p => p.Name), (xp, yp) => JTokenComparer.Instance.Compare(xp, yp)))
            if (propertyComp != 0)
                return propertyComp;
        if ((comp = x.Count.CompareTo(y.Count)) != 0)
            return comp;
        return 0;
    }
}

class JArrayComparer : JContainerOrderedComparerBase<JArray>
{
    protected override int CompareDerived(JArray x, JArray y)
    {
        int comp;
        if ((comp = CompareItemsInOrder(x, y)) != 0)
            return comp;
        return 0;
    }
}

class JConstructorComparer : JContainerOrderedComparerBase<JConstructor>
{
    protected override int CompareDerived(JConstructor x, JConstructor y)
    {
        int comp;
        if ((comp = x.Name.CompareTo(y.Name)) != 0)
            return comp;
        if ((comp = CompareItemsInOrder(x, y)) != 0)
            return comp;
        return 0;
    }
}

class JValueComparer : JTokenComparerBase<JValue>
{
    protected override int CompareDerived(JValue x, JValue y)
    {
        return Comparer<JToken>.Default.Compare(x, y); // JValue implements IComparable<JValue>
    }
}
公共类JTokenComparer:IComparer
{
公共静态JTokenComparer实例{get{return Instance;}}
静态JTokenComparer实例;
静态JTokenComparer()
{
实例=新的JTokenComparer();
}
只读词典;
JTokenComparer()
{
dict=新词典
{
//顺序的选择是半随意的,但将值放在首位似乎是合理的。
{typeof(JValue),新的KeyValuePair(0,新的JValueComparer())},
{typeof(JProperty),新的KeyValuePair(1,新的JPropertyComparer())},
{typeof(JArray),新的KeyValuePair(2,新的JArrayComparer())},
{typeof(JObject),new KeyValuePair(3,new JObjectComparer())},
{typeof(JConstructor),新的KeyValuePair(4,新的JConstructorComparer())},
};
}
#地区I比较成员
公共整数比较(JToken x,JToken y)
{
如果(x是JRaw | | y是JRaw)
抛出新的InvalidOperationException(“JRaw类型的令牌无法排序”);
if(object.ReferenceEquals(x,y))
返回0;
else如果(x==null)
返回-1;
如果(y==null),则为else
返回1;
var typeData1=dict[x.GetType()];
var typeData2=dict[y.GetType()];
国际公司;
如果((comp=typeData1.Key.CompareTo(typeData2.Key))!=0)
返回补偿;
if(typeData1.Value!=typeData2.Value)
抛出新的InvalidOperationException(“不一致的字典值”);//内部错误
返回typeData2.Value.Compare(x,y);
}
#端区
}
抽象类JTokenComparerBase:IComparer,其中TJToken:JToken
{
受保护的TJToken检查类型(JToken项)
{
if(item!=null&&item.GetType()!=typeof(TJToken))
抛出新ArgumentException(string.Format(“标记\“{1}\”的实际类型{0}与预期类型{2}”不匹配),item.GetType(),item,typeof(TJToken));
返回(TJToken)项;
}
受保护的bool-TryBaseCompare(TJToken x、TJToken y、out-int比较)
{
支票类型(x);
支票类型(y);
if(object.ReferenceEquals(x,y))
{
比较=0;
返回true;
}
else如果(x==null)
{
比较=-1;
返回true;
}
如果(y==null),则为else
{
比较=1;
返回true;
}
比较=0;
返回false;
}
比较驱动的受保护摘要(TJToken x,TJToken y);
受保护的整数令牌比较(JToken x,JToken y)
{
var tx=检查类型(x);
var ty=支票类型(y);
国际公司;
如果(TryBaseCompare(tx、ty、out comp))
返回补偿;
返回比较驱动(tx,ty);
}
#地区I比较成员
int IComparer.Compare(JToken x,JToken y)
{
返回标记比较(x,y);
}
#端区
}
抽象类JContainerOrderedComparerBase:JTokenComparerBase,其中TJToken:JContainer
{
受保护的整数比较项顺序(TJToken x,TJToken y)
{
国际公司;
//字典顺序:在项目数之前对项目进行排序。
对于(int)i=0,n=Math.Min(x.Count,
public class JTokenComparer : IComparer<JToken>
{
    public static JTokenComparer Instance { get { return instance; } }

    static JTokenComparer instance;

    static JTokenComparer()
    {
        instance = new JTokenComparer();
    }

    readonly Dictionary<Type, KeyValuePair<int, IComparer<JToken>>> dict;

    JTokenComparer()
    {
        dict = new Dictionary<Type, KeyValuePair<int, IComparer<JToken>>>
        {
            // Order chosen semi-arbitrarily.  Putting values first seems reasonable though.
            {typeof(JValue), new KeyValuePair<int, IComparer<JToken>>(0, new JValueComparer()) },
            {typeof(JProperty), new KeyValuePair<int, IComparer<JToken>>(1, new JPropertyComparer()) },
            {typeof(JArray), new KeyValuePair<int, IComparer<JToken>>(2, new JArrayComparer()) },
            {typeof(JObject), new KeyValuePair<int, IComparer<JToken>>(3, new JObjectComparer()) },
            {typeof(JConstructor), new KeyValuePair<int, IComparer<JToken>>(4, new JConstructorComparer()) },
        };
    }

    #region IComparer<JToken> Members

    public int Compare(JToken x, JToken y)
    {
        if (x is JRaw || y is JRaw)
            throw new InvalidOperationException("Tokens of type JRaw cannot be sorted");
        if (object.ReferenceEquals(x, y))
            return 0;
        else if (x == null)
            return -1;
        else if (y == null)
            return 1;

        var typeData1 = dict[x.GetType()];
        var typeData2 = dict[y.GetType()];

        int comp;
        if ((comp = typeData1.Key.CompareTo(typeData2.Key)) != 0)
            return comp;
        if (typeData1.Value != typeData2.Value)
            throw new InvalidOperationException("inconsistent dictionary values"); // Internal error
        return typeData2.Value.Compare(x, y);
    }

    #endregion
}

abstract class JTokenComparerBase<TJToken> : IComparer<JToken> where TJToken : JToken
{
    protected TJToken CheckType(JToken item)
    {
        if (item != null && item.GetType() != typeof(TJToken))
            throw new ArgumentException(string.Format("Actual type {0} of token \"{1}\" does not match expected type {2}", item.GetType(), item, typeof(TJToken)));
        return (TJToken)item;
    }

    protected bool TryBaseCompare(TJToken x, TJToken y, out int comparison)
    {
        CheckType(x);
        CheckType(y);
        if (object.ReferenceEquals(x, y))
        {
            comparison = 0;
            return true;
        }
        else if (x == null)
        {
            comparison = -1;
            return true;
        }
        else if (y == null)
        {
            comparison = 1;
            return true;
        }
        comparison = 0;
        return false;
    }

    protected abstract int CompareDerived(TJToken x, TJToken y);

    protected int TokenCompare(JToken x, JToken y)
    {
        var tx = CheckType(x);
        var ty = CheckType(y);
        int comp;
        if (TryBaseCompare(tx, ty, out comp))
            return comp;
        return CompareDerived(tx, ty);
    }

    #region IComparer<JToken> Members

    int IComparer<JToken>.Compare(JToken x, JToken y)
    {
        return TokenCompare(x, y);
    }

    #endregion
}

abstract class JContainerOrderedComparerBase<TJToken> : JTokenComparerBase<TJToken> where TJToken : JContainer
{
    protected int CompareItemsInOrder(TJToken x, TJToken y)
    {
        int comp;
        // Dictionary order: sort on items before number of items.
        for (int i = 0, n = Math.Min(x.Count, y.Count); i < n; i++)
            if ((comp = JTokenComparer.Instance.Compare(x[i], y[i])) != 0)
                return comp;
        if ((comp = x.Count.CompareTo(y.Count)) != 0)
            return comp;
        return 0;
    }
}

class JPropertyComparer : JTokenComparerBase<JProperty>
{
    protected override int CompareDerived(JProperty x, JProperty y)
    {
        int comp;
        if ((comp = x.Name.CompareTo(y.Name)) != 0)
            return comp;
        return JTokenComparer.Instance.Compare(x.Value, y.Value);
    }
}

class JObjectComparer : JTokenComparerBase<JObject>
{
    protected override int CompareDerived(JObject x, JObject y)
    {
        int comp;
        // Dictionary order: sort on items before number of items.
        // Order both property sequences to preserve reflexivity.
        foreach (var propertyComp in x.Properties().OrderBy(p => p.Name).Zip(y.Properties().OrderBy(p => p.Name), (xp, yp) => JTokenComparer.Instance.Compare(xp, yp)))
            if (propertyComp != 0)
                return propertyComp;
        if ((comp = x.Count.CompareTo(y.Count)) != 0)
            return comp;
        return 0;
    }
}

class JArrayComparer : JContainerOrderedComparerBase<JArray>
{
    protected override int CompareDerived(JArray x, JArray y)
    {
        int comp;
        if ((comp = CompareItemsInOrder(x, y)) != 0)
            return comp;
        return 0;
    }
}

class JConstructorComparer : JContainerOrderedComparerBase<JConstructor>
{
    protected override int CompareDerived(JConstructor x, JConstructor y)
    {
        int comp;
        if ((comp = x.Name.CompareTo(y.Name)) != 0)
            return comp;
        if ((comp = CompareItemsInOrder(x, y)) != 0)
            return comp;
        return 0;
    }
}

class JValueComparer : JTokenComparerBase<JValue>
{
    protected override int CompareDerived(JValue x, JValue y)
    {
        return Comparer<JToken>.Default.Compare(x, y); // JValue implements IComparable<JValue>
    }
}
    public static JToken Normalize(this JToken token)
    {
        var result = token;

        switch (token.Type)
        {
            case JTokenType.Object:
                var jObject = (JObject)token;

                if (jObject != null && jObject.HasValues)
                {
                    var newObject = new JObject();

                    foreach (var property in jObject.Properties().OrderBy(x => x.Name).ToList())
                    {
                        var value = property.Value as JToken;
                        if (value != null)
                        {
                            value = Normalize(value);
                        }

                        newObject.Add(property.Name, value);
                    }
                    return newObject;
                }

                break;

            case JTokenType.Array:

                var jArray = (JArray)token;

                if (jArray != null && jArray.Count > 0)
                {
                    var normalizedArrayItems = jArray
                        .Select(x => Normalize(x))
                        .OrderBy(x => x.ToString(), StringComparer.Ordinal);

                    result = new JArray(normalizedArrayItems);
                }

                break;
            default:
                break;
        }

        return result;
    }