swaggest / json-diff

JSON diff/rearrange/patch/pointer library for PHP
MIT License
220 stars 30 forks source link

Wrong indexes of removed array items #41

Closed germanovs closed 3 years ago

germanovs commented 3 years ago

Hello! Here is the situation: I have 3 items in origin array and remove last 2 of them. In exported patch there are 2 removes, but with similar indexes. This issue does not appear on added items.

Example. Origin JSON.

{
  "companies": {
    "list": [
      {
        "name": "Company 1",
        "orgnumber": "111"
      }, {
        "name": "Company 2",
        "orgnumber": "222"
      }, {
        "name": "Company 3",
        "orgnumber": "333"
      }
    ]
  },
  "contacts": {
    "list": [
      {
        "name": "Ivan",
        "phone": "11111"
      }
    ]
  }
}

New JSON.

{
  "companies": {
    "list": [
      {
        "name": "Company 1",
        "orgnumber": "111"
      }
    ]
  },
  "contacts": {
    "list": [
      {
        "name": "Ivan",
        "phone": "11111"
      },
      {
        "name": "Petr",
        "phone": "22222"
      },
      {
        "name": "Victor",
        "phone": "33333"
      }
    ]
  }
}

Code

$r = new Swaggest\JsonDiff\JsonDiff((json_decode(file_get_contents('origin.json'))), (json_decode(file_get_contents('new.json'))));
print_r(Swaggest\JsonDiff\JsonPatch::export($r->getPatch()));

Output

Array
(
    [0] => stdClass Object
        (
            [op] => remove
            [path] => /companies/list/1
        )

    [1] => stdClass Object
        (
            [op] => remove
            [path] => /companies/list/1
        )

    [2] => stdClass Object
        (
            [value] => stdClass Object
                (
                    [name] => Petr
                    [phone] => 22222
                )

            [op] => add
            [path] => /contacts/list/1
        )

    [3] => stdClass Object
        (
            [value] => stdClass Object
                (
                    [name] => Victor
                    [phone] => 33333
                )

            [op] => add
            [path] => /contacts/list/2
        )

)

Companies with indexes 1 and 2 are removed, but it paths both indexes are 1. At the same time paths of added items in Contacts are ok (1 and 2). Or I miss something?

Thanks in advance!

vearutop commented 3 years ago

I think this is an expected, although maybe confusing, behavior. As per RFC:

If removing an element from an array, any elements above the specified index are shifted one position to the left.

So in such case, if you have [0,1,2] and you remove index 1 twice you end up having [0]: