代码之家  ›  专栏  ›  技术社区  ›  Nandakumar1712

如何使用C比较两个Json对象#

  •  2
  • Nandakumar1712  · 技术社区  · 6 年前

    我有两个Json对象需要比较,如下所示。我正在使用Newtonsoft库进行Json解析。

    string InstanceExpected = jsonExpected;
    string InstanceActual = jsonActual;
    var InstanceObjExpected = JObject.Parse(InstanceExpected);
    var InstanceObjActual = JObject.Parse(InstanceActual);
    

    我用流利的断言来比较。但问题是,Fluent断言只有在属性计数/名称不匹配时才会失败。如果json值不同,则传递。当价值观不同时,我要求失败。

    InstanceObjActual.Should().BeEquivalentTo(InstanceObjExpected);
    

    例如,我将实际的和预期的json进行比较,如下所示。并用上述比较的方法使它们通过,这是错误的。

    {
      "Name": "20181004164456",
      "objectId": "4ea9b00b-d601-44af-a990-3034af18fdb1%>"  
    }
    
    {
      "Name": "AAAAAAAAAAAA",
      "objectId": "4ea9b00b-d601-44af-a990-3034af18fdb1%>"  
    }
    
    4 回复  |  直到 6 年前
        1
  •  22
  •   Rui Jarimba    6 年前

    我做了更深入的研究,找到了OP的测试代码不能按预期运行的原因。我可以通过安装和使用 FluentAssertions.Json

    一件重要的事:

    一定要包括 using FluentAssertions.Json 否则为假 可能出现阳性反应。

    测试代码如下:

    using FluentAssertions;
    using FluentAssertions.Json;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using NUnit.Framework;
    
    [TestFixture]
    public class JsonTests
    {
        [Test]
        public void JsonObject_ShouldBeEqualAsExpected()
        {
            JToken expected = JToken.Parse(@"{ ""Name"": ""20181004164456"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");
            JToken actual = JToken.Parse(@"{ ""Name"": ""AAAAAAAAAAAA"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");
    
            actual.Should().BeEquivalentTo(expected);
        }
    }
    

    Unit test results

        2
  •  18
  •   Jesse de Wit    6 年前

    考虑使用 JToken.DeepEquals() Newtonsoft提供的方法。不管您使用的是哪种测试框架,它看起来都有点像这样:

    Console.WriteLine(JToken.DeepEquals(InstanceObjActual, InstanceObjExpected));
    // false
    
        3
  •  4
  •   Community    4 年前

    public void RemoveTwins(ref BreadthFirst bf1, ref BreadthFirst bf2) {
        JsonNode traversal = bf1.Next();
        Boolean removed = false;
        do {
            if (!removed) {
                if (bf2.Current != null) while (bf1.Level == bf2.Level && bf2.Next() != null) ;
                if (bf2.Current != null) while (bf1.Level != bf2.Level && bf2.Next() != null) ;
                else bf2.Current = bf2.root;
            }
            else traversal = bf1.Next();
            if (bf2.Level < 0) bf2.Current = bf2.Root;
            do {
                removed = bf1.NextAs(bf1.src, bf2, bf2.src);
                if (removed && bf1.Orphan && bf2.Orphan) {
                    JsonNode same = bf1.Current.Parent;
                    traversal = bf1.RemoveCurrent();
                    same = bf2.Current.Parent;
                    bf2.RemoveCurrent();
                    bf1.UpdateLevel();
                    bf2.UpdateLevel();
                    if (traversal == null
                    || bf1.Root == null || bf2.Root == null
                    || (bf1.Level == 0 && bf1.Current.NodeBelow == null)) {
                        traversal = null;
                        break;
                    }
                } else
                if (!removed) {
                    break; 
                } else removed = false;
            } while (removed);
            if (!removed) traversal = bf1.Next();
        } while (traversal != null);
    }
    


    旧的CSV版本,也排序输入提到我的问题在这里 How to compare big JSON's? (新的一个没有,所以当其中一个对象的顺序颠倒时,它可能会非常慢——在解析过程中排序会更容易,或者至少在第一步搜索时比较twins的两个邻居)

        4
  •  2
  •   Rui Jarimba    6 年前

    一种方法是将json字符串反序列化为C#对象并进行比较。

    与使用相比,这种方法需要更多的工作 JToken.DeepEquals

    public class Entity
    {
        [JsonProperty("Name")]
        public string Name { get; set; }
    
        [JsonProperty("objectId")]
        public string ObjectId { get; set; }
    }
    

    [TestFixture]
    public class JsonTests
    {
        [Test]
        public void JsonString_ShouldBeEqualAsExpected()
        {
            string jsonExpected = @"{ ""Name"": ""20181004164456"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";
            string jsonActual = @"{ ""Name"": ""AAAAAAAAAAAA"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";
    
            Entity expectedObject = JsonConvert.DeserializeObject<Entity>(jsonExpected);
            Entity actualObject = JsonConvert.DeserializeObject<Entity>(jsonActual);
    
            actualObject.Should().BeEquivalentTo(expectedObject);
        }
    }
    

    Unit test results

        5
  •  -1
  •   Itamar Kerbel    6 年前

    将json反序列化为C对象后,正确的方法是在反序列化的类中实现IComparable接口并比较这两个对象。

    所以:

    using System;
    using System.Collections.Generic;
    
    class MyObj : IComparable<MyObj>
    {
        public string Name { get; set; }
        public string ObjectID { get; set; }
    
        public int CompareTo(MyObj other)
        {
            if ((this.Name.CompareTo(other.Name) == 0) &&
                (this.ObjectID.CompareTo(other.ObjectID) == 0))
            {
                return 0;
            }
            return -1;
        }
    }