Newtonsoft.json: DeepEquals fails when order of array elements is different

Created on 19 Sep 2017  路  3Comments  路  Source: JamesNK/Newtonsoft.Json

I am comparing two parsed strings and this has worked flawlessly for all of our tests so far.
However, I have encountered a case where DeepEquals fails when the order of objects in an array isn't identical.
The test passes if I update one Json to match the other.

// data is a string (a .json file read as text)
JToken expectedJson = JToken.Parse(data).SelectToken(jPath);
// Content is a string (the response body as returned by RestSharp
JToken jsonResponse = JToken.Parse(Content);
return JToken.DeepEquals(expectedJson, jsonResponse);

Source/destination JSON

First, the JSON returned by the API:

{
  "isHohrResponse": true,
  "messages": [],
  "success": true,
  "data": {
    "totalPaid": 301,
    "requiresConfirmation": false,
    "jobs": [
      {
        "jobId": "600dea62-f084-4459-9e91-8e809884d130",
        "jobName": "Job I",
        "fee": 76,
        "totalPayed": 76,
        "paymentUserInfo": [
          {
            "id": "ab2b408d-1e44-408e-b8e4-df779e31e37d",
            "name": "Frederik25 D",
            "isStarted": true,
            "hasLiked": true
          }
        ],
        "requiresConfirmation": false
      },
      {
        "jobId": "ca0a14b4-0206-45ba-9c31-cd5fa7745058",
        "jobName": "Job H",
        "fee": 75,
        "totalPayed": 225,
        "paymentUserInfo": [
          {
            "id": "3a1a91cf-03f9-4f06-9679-c339ddc295d7",
            "name": "Frederik23 D",
            "isStarted": true,
            "hasLiked": true
          },
          {
            "id": "9e323b98-08dc-4bc0-854e-f42711258252",
            "name": "Frederik26 D",
            "isStarted": true,
            "hasLiked": true
          },
          {
            "id": "68ab2e64-6356-4263-a8cb-2953deb675b6",
            "name": "Frederik24 D",
            "isStarted": true,
            "hasLiked": true
          }
        ],
        "requiresConfirmation": false
      }
    ]
  }
}

Now, the JSON having the final paymentUserInfo objects in a different order:

{
  "isHohrResponse": true,
  "messages": [],
  "success": true,
  "data": {
    "totalPaid": 301,
    "requiresConfirmation": false,
    "jobs": [
      {
        "jobId": "600dea62-f084-4459-9e91-8e809884d130",
        "jobName": "Job I",
        "fee": 76,
        "totalPayed": 76,
        "paymentUserInfo": [
          {
            "id": "ab2b408d-1e44-408e-b8e4-df779e31e37d",
            "name": "Frederik25 D",
            "isStarted": true,
            "hasLiked": true
          }
        ],
        "requiresConfirmation": false
      },
      {
        "jobId": "ca0a14b4-0206-45ba-9c31-cd5fa7745058",
        "jobName": "Job H",
        "fee": 75,
        "totalPayed": 225,
        "paymentUserInfo": [
          {
            "id": "68ab2e64-6356-4263-a8cb-2953deb675b6",
            "name": "Frederik24 D",
            "isStarted": true,
            "hasLiked": true
          },
          {
            "id": "9e323b98-08dc-4bc0-854e-f42711258252",
            "name": "Frederik26 D",
            "isStarted": true,
            "hasLiked": true
          },
          {
            "id": "3a1a91cf-03f9-4f06-9679-c339ddc295d7",
            "name": "Frederik23 D",
            "isStarted": true,
            "hasLiked": true
          }
        ],
        "requiresConfirmation": false
      }
    ]
  }
}

Most helpful comment

Made a custom difference checker that fires as soon as DeepEquals fails. Works like a charm. Still it would be nice to be able to ignore array order (boolean parameter to DeepEquals?)

All 3 comments

I have experienced the same issue. Here is a link reproducing it. https://dotnetfiddle.net/SEMSJZ

I found a workaround for now :) But it does involve creating a class to deserialize the json

var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject<SomeClass>(expected));
var mappedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject<SomeClass>(mapped));
Assert.True(JToken.DeepEquals(expectedJson, mappedJson));

Made a custom difference checker that fires as soon as DeepEquals fails. Works like a charm. Still it would be nice to be able to ignore array order (boolean parameter to DeepEquals?)

Was this page helpful?
0 / 5 - 0 ratings