JSON diffing

This is a followup on my previous creation "jsonMerge". The jsonDiff is capable of extracting all differences between two JSON structures, thus returning a JSON structure only contaning diff key/value pairs.

Download this example: jsonDiff.zip

Variable json1 initially contains:


Variable json2 initially contains:


Result of calling jsonDataHandler.diff(json1, json2) where cyclic references has been removed to allow non-infinite output:


The class LGPL license:

// Author: Michael Schøler, 2008
// LGPL license, use as you like, don't hold me responsible for success or failure though
Array.prototype.compareTo = function(compareAry) {
  if (this.length === compareAry.length) {
    var i;
    for (i = 0; i < compareAry.length; i+=1) {
      if (Object.isArray(this[i]) === true) {
        if (this[i].compareTo(compareAry[i]) === false) {
          return false;
        }
        continue;
      }
      else if (this[i] !== compareAry[i]) {
        return false;
      }
    }
    return true;
  }
  return false;
};
var jsonDataHandler = {
  diff: function(j1, j2) {
    if (typeof this.diffing === "undefined" || this.diffing === 0) {
      this.diffCyclicCheck = [];
      this.diffing = 0;
    }
    var diffRes = {};
    this.diffing += 1;
    if (typeof j1 === "undefined") {
      j1 = {};
    }
    if (typeof j2 === "undefined") {
      j2 = {};
    }
    if (typeof this.diffCyclicCheck === "undefined") {
      this.diffCyclicCheck = [];
    }
    var key, bDiff;
    for (key in j2) if (j2.hasOwnProperty(key)) {  
      bDiff = false;
      if (typeof j1[key] === "undefined" || typeof j1[key] != typeof j2[key]) {
        bDiff = true;
      }
      else if (j1[key] !== j2[key]) {
        if (typeof j2[key] === "object") {
          if (this.diffCyclicCheck.indexOf(j2[key]) >= 0) {
            break;
          }
          else if (Object.isArray(j2[key])) {
            if (j1[key].length !== j2[key].length || j1[key] !== j2[key]) {
              if (j2[key].compareTo(j1[key]) === false) {
                bDiff = true;
              }
            }
          }
          else if (typeof j1[key] === "object") {
            var dR = this.diff(j1[key], j2[key]);
            if (Object.keys(dR).length > 0) {
              diffRes[key] = dR;
            }
          }
          else {
            bDiff = true;
          }
          this.diffCyclicCheck.push(j2[key]);
        }
        else if (j1[key] !== j2[key]) {
          bDiff = true;
        }
      }
      if (bDiff) {
        diffRes[key] = j2[key];
      }
    }
    for (key in j1) if (j1.hasOwnProperty(key)) { 
      bDiff = false;
      if (typeof j2[key] === "undefined") {
        diffRes[key] = j1[key];
      }
    }
    this.diffing -= 1;
    return diffRes;
  }
};