cujojs / jiff

JSON Patch and diff based on rfc6902
Other
627 stars 41 forks source link

Object Array Matching #36

Open balihoo-dengstrom opened 8 years ago

balihoo-dengstrom commented 8 years ago

I'm trying to find a way to reduce unnecessary array patches and I'm curious if there is a solution for this scenario. I have items that contain an array of objects like this:

{
    "things": [
        {
            "id": "123",
            "foo": "jiff",
            "bar": "jiff"
        },
        {
            "id": "abc",
            "foo": "jiff",
            "bar": "jiff"
        }
    ]
}

Currently when I diff changes to this type of structure I end up with add and remove operations for entire "things" objects even when only a single property in the object changes (e.g. things[0].foo changes but the other properties remain constant).

I understand why this happens but is there a way to provide a hint to jiff so that it could match array objects on their "id" value? Or is that something that a feature that you would consider including?

larvanitis commented 6 years ago

Providing a custom hash function to the diff method is what you are looking for. In this example the object's id is returned, if it exists (and truthy), otherwise the default hash function is used (taken from jiff's code).

jiff.diff(a, b, {hash: hashFn});

function hashFn(x) {
  if (x && x.id) {
    return x.id;
  }
  return defaultHash(x);
}

function defaultHash(x) {
  return isValidObject(x) || isArray(x) ? JSON.stringify(x) : x;
}

function isValidObject(x) {
  return x !== null && Object.prototype.toString.call(x) === '[object Object]';
}

function isArray(x) {
  return Object.prototype.toString.call(x) === '[object Array]';
}