Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difference ignoring order of elements in an array. #33

Closed
webpunk opened this issue Sep 23, 2020 · 11 comments
Closed

Difference ignoring order of elements in an array. #33

webpunk opened this issue Sep 23, 2020 · 11 comments

Comments

@webpunk
Copy link

webpunk commented Sep 23, 2020

Hi,

is there a way to get the difference between two JSON objects while ignoring the order of elements in an array. For instance, the following example currently returns 4 differences but should return 0.

$diff = new \Swaggest\JsonDiff\JsonDiff( json_decode('{"data": [{"A": 1},{"B": 2}]}'), json_decode('{"data": [{"B": 2},{"A": 1}]}'), \Swaggest\JsonDiff\JsonDiff::REARRANGE_ARRAYS ); echo "\n" . $diff->getDiffCnt() . "\n";

Thanks!

@vearutop
Copy link
Member

vearutop commented Sep 23, 2020

Hello, REARRANGE_ARRAYS is a best effort feature that targets homogenic arrays.
In order to be rearranged, both arrays have to have at least one key that is avaialble in all items and that key needs to have unique values in original array.

If your values would have beed like these:

{"data": [{"A": 1, "C": 1},{"B": 2, "C": 2}]}
{"data": [{"B": 2, "C": 2},{"A": 1, "C": 1}]}

they would produce empty diff.

The reason for such an approach is to reduce computational complexity, and main usecase for the initial implementation was to address non-semantic differences in swagger parameters.

Solving general case like yours would need some quadratic recursive comparisons to understand that a particular array item is equal to another one. Is this case important for you? I think it can be implemented as some additional option with a performance impact disclaimer.

@webpunk
Copy link
Author

webpunk commented Sep 23, 2020

Thanks for the swift reply! Unfortunately, I can't influence the format of the JSON object because it is provided by an API. So this would actually be an important feature for me. Maybe I can customize the code of JSONDiff if you show me where to find the corresponding code parts?

@vearutop
Copy link
Member

@webpunk I have an idea how to implement rearrangement based on elements equality with reasonable performance, optimistically will make it in couple of days.

@webpunk
Copy link
Author

webpunk commented Sep 24, 2020

@vearutop yes, that would be great! Please, let me know if I can help...

@vearutop
Copy link
Member

@webpunk please check if new v3.8.0 works for you. No new option needed, JsonDiff::REARRANGE_ARRAYS should suffice.

@webpunk
Copy link
Author

webpunk commented Sep 25, 2020

Hi @vearutop ! Thanks a lot for the new version. I have just tested it. For the following two JSON objects, JSONDiff still reports a difference that I can't see.

Example.zip

@vearutop vearutop reopened this Sep 25, 2020
vearutop added a commit that referenced this issue Sep 25, 2020
vearutop added a commit that referenced this issue Sep 25, 2020
@vearutop
Copy link
Member

@webpunk thanks for the test case, please check v3.8.1.

@webpunk
Copy link
Author

webpunk commented Sep 26, 2020

@vearutop unfortunately, there still seems to be a problem with an array of strings. I've attached another example. Thx!
Example2.zip

@vearutop
Copy link
Member

@webpunk I've tried this example with a test case:

    public function testExample2() {
        $ex1 = json_decode(file_get_contents(__DIR__ . '/../assets/Example1.json'));
        $ex2 = json_decode(file_get_contents(__DIR__ . '/../assets/Example2.json'));

        $diff = new JsonDiff($ex1, $ex2, JsonDiff::REARRANGE_ARRAYS);
        $this->assertEquals(0, $diff->getDiffCnt());
    }

and the test passed (no differences found).

Could you elaborate the problem that you are seeing with array of strings, or maybe steps to reproduce?

@webpunk
Copy link
Author

webpunk commented Sep 26, 2020

@vearutop Sorry... that was a mistake on my part! Now it works perfectly. Thanks a lot!

@melnikaite
Copy link

Sometimes ordering of fields name and code swaps, having REARRANGE_ARRAYS it supposed to be ignored, but in fact treated as difference

{
    "id": 826907,
    "contracts": [
        {
            "id": 715559,
            "product": {
                "name": "Friends",
                "code": "friends"
            }
        }
    ]
}
code
<?php

require __DIR__ . '/../vendor/autoload.php';

use Swaggest\JsonDiff\JsonDiff;

$v1 = <<<JSON
{
    "id": 826907,
    "contracts": [
        {
            "id": 715559,
            "product": {
                "code": "friends",
                "name": "Friends"
            }
        }
    ]
}
JSON;
$v2 = <<<JSON
{
    "id": 826907,
    "contracts": [
        {
            "id": 715559,
            "product": {
                "name": "Friends",
                "code": "friends"
            }
        }
    ]
}
JSON;

$diff = new JsonDiff($v1, $v2, JsonDiff::REARRANGE_ARRAYS);
$patch = json_encode($diff->getPatch()->jsonSerialize());
echo $patch;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants