-
Notifications
You must be signed in to change notification settings - Fork 157
Description
When diffing arrays of objects, if an object was moved and also modified, the diff would generate a remove and add operation because the objects were not strictly equal. This made patches less readable/ less obvious.
Enhancement:
Added a optional "smart equals" for array objects during diffing. Now, if an object is moved and modified, the diff generates a move and a replace operation, making the patch more accurate and easier to understand.
Same idea as implemented in the typescript library -> https://github.com/benjamine/jsondiffpatch
Benefit:
More intuitive and minimal patches for arrays of objects
Better reflects intent when objects are moved and changed
Example:
Usage:
JsonNodeEqualsRefFunction objectIdEqualsRefFunction = new JsonNodeEqualsRefFunction() {
@Override
public Object getEqualsRef(JsonNode jsonNode) {
return jsonNode.has("id") ? jsonNode.get("id").asInt() : jsonNode;
}
};
JsonNode actualPatch = JsonDiff.asJson(first, second, DiffFlags.defaults(), objectIdEqualsRefFunction);
JSON Diff:
// Example: Move array element and modify its property
{
"message": "Move array element and modify its property",
"first": [
{"id": 1, "val": "a"},
{"id": 2, "val": "b"},
{"id": 3, "val": "c"}
],
"second": [
{"id": 3, "val": "changed"},
{"id": 1, "val": "a"},
{"id": 2, "val": "b"}
],
"patch": [
{"op": "move", "from": "/2", "path": "/0"},
{"op": "replace", "path": "/0/val", "value": "changed"}
]
}
With the current main or without a custom equals ref function in this branch this results in:
[
{"op": "remove", "path": "/2"},
{"op": "add", "path": "/0", "value": {"id": 3, "val": "changed"}}
]