flitbit / diff

Javascript utility for calculating deep difference, capturing changes, and applying changes across objects; for nodejs and the browser.
MIT License
2.99k stars 213 forks source link

Is there any way to return a JSON difference object instead of descriptor alone? #110

Closed brydko closed 6 years ago

brydko commented 7 years ago

Hello. I would like to obtain an actual difference between 2 JSON with same schema.

JSON1 ->

{"key1":[{"prop1":"a","name":"a","status":"active","values":["val1"]}],
 "key2":[{"property":"oneProperty","name":"name","type":"someType"},
{"property":"differentProperty","name":"someOtherName","type":"someOtherType"},]};

JSON2 ->

{"key1":[{"prop1":"a","name":"a","status":"active","values":["val1"]}],
 "key2":[{"property":"oneProperty","name":"name","type":"someType"}]};

The object difference is correctly obtained ->

[{"kind":"A",
    "path":["key2"],
    "index":1,
    "item":{"kind":"D","lhs":{"property":"differentProperty","name":"someOtherName","type":"someOtherType"}}}];

What I am actually trying to get is the actual difference itself (I don't care if some property was added or deleted). So the result I'm expecting is

{"key2":[{"property":"differentProperty","name":"someOtherName","type":"someOtherType"}]}

Is there any way to obtain it straight away or should I rather parse the difference object myself in some fashion ?

Thank you

flitbit commented 6 years ago

Truly, with a little help from our friends:

const diff = require('deep-diff');
const ptr = require('json-ptr');

let original = {
  points: [{ x: 1, y: 2 }, { x: 5, y: 2 }, { x: 3, y: 4 }],
  obj: { id: 5, name: "MyName" }
};

let modified = JSON.parse(JSON.stringify(original));

modified.points[0].x = 7;
modified.obj.name = 'Wilbur Finkle';

const differences = diff(original, modified);

// Produce an object that represents the delta between original and modified objects
const delta = differences.reduce((acc, record) => {
  // Only process edits and newly added values
  if (record.kind === 'E' || record.kind === 'N') {
    ptr.set(
      acc,                            // target
      ptr.encodePointer(record.path), // pointer; from path
      record.rhs,                     // modified value
      true                            // force; creates object graph
    );
  }
  return acc;
}, {});

console.log(JSON.stringify(delta, null, '  '));

Produces:

{
  "points": [
    {
      "x": 7
    }
  ],
  "obj": {
    "name": "Wilbur Finkle"
  }
}