JavaScript Object Notation (JSON) Patch (RFC6902)—not to be confused with JSON Merge Patch (RFC7386)—has several examples of array manipulation:
Adding an Array Element:
[
{ "op": "add", "path": "/foo/1", "value": "qux" }
]
Removing an Array Element:
[
{ "op": "remove", "path": "/foo/1" }
]
However, these mechanisms alone seem to be poorly suited for concurrent updates and require exact tracking of the element positions.
If we take an example document that can be manipulated:
{
"@context": "/contexts/organizaion",
"@id": "/organizations/1",
"name": "Stack Overflow",
"members": ["/users/1", "/users/2", "/users/3"]
}
If two writers try to remove "/users/2"
from members at the same time using [{ "op": "remove", "path": "/members/2" }]
, then "/users/3"
will be removed from members as well. This problem can be circumvented by using the "test" operation:
[
{ "op": "test", "path": "/members/1", "value": "/users/2" },
{ "op": "remove", "path": "/members/2" }
]
This option seems far from optimal. If the list positioning/ordering has changed since the last GET request, the client has to issue another GET request, find the element position and issue another PATCH hoping that the position has not changed in the meantime.
Is there a better way to do array manipulation using PATCH?