James Munsch


function isObject(obj){
    return typeof obj === 'object' && !Array.isArray(obj) && obj !== null
  }

  /**
   * //TODO this is only a helper until the payloads become more stable
   * @name deepCompareTypeExistingKeys
   * @description being used to do a deep comparision of nested objects comparing obj1's types & keys to obj2's types & keys
   * @param obj1 a working payload
   * @param obj2 a payload to check nested types and keys
   * @param results an array of error message or an empty array
   * @param parentKey kwarg to temp set the keyPath some.nested.object
   * @returns {*}
   */
  function deepCompareTypeExistingKeys(obj1, obj2, results, parentKey){
    results ? results : results = [];
    parentKey ? parentKey : parentKey = 'NonWorkingPayload'
    var originalParentKey = parentKey;
    // Check if they are both objects
    if (isObject(obj1) && isObject(obj2)) {
      for (var key in obj1) {
        if (obj2[key] !== undefined) {
          // check types for 'string' 'number' 'boolean' 'undefined'
          if (typeof obj1[key] !== typeof obj2[key]) {
            // push the type mismatch error into the results
            results.push({'errorMsg': 'Type MisMatch',
              'keyPath': parentKey + '.' + key,
              'key': key,
              'WorkingPayloadValue': obj1[key],
              'NonWorkingPayloadValue': obj2[key]})
          }
          // check if they are both arays
          if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])){
            obj2[key].forEach(function(arrayObj2){
              // set the keyPath
              parentKey = parentKey + '.' + key;
              // recurse into child object
              deepCompareTypeExistingKeys(obj1[key][0], arrayObj2, results, parentKey);
              // unset the keyPath to current level
              parentKey = originalParentKey;
            })
          }
          // set the keyPath
          parentKey = parentKey + '.' + key;
          // recurse into child object
          deepCompareTypeExistingKeys(obj1[key], obj2[key], results, parentKey);
          // unset the keyPath to current level
          parentKey = originalParentKey;
        }
        // obj1 has a key, but obj2 doesn't
        else {
          results.push({'errorMsg': 'Missing Key',
            'key': key,
            'keyPath': parentKey + '.' + key,
            'WorkingPayloadValue': obj1[key],
            'NonWorkingPayloadValue': obj2[key]})
        }
      }
      // return the results array back up the recursion tree
      return results
    }
    // Wasnt an object
    else {
      // skip it
      return results
    }
  };
  

The reason for me writing this function was to be able to figure out the differences between two json payloads, or javascript objects, based on their keys, and types.

My eyes hurt quite a bit when trying to figure out the differences between '2' an 2. Trying to hit an endpoint that is "strongly typed" is hard when dealing with 100s of keys and values.


I can see the benefit of something like typescript, or jszero.


Example input:

  var obj1 = {hello: 1,  someArr:[{'hiagain': 123,'hiagain2': '333'}], someArr2:[{'again': 123,'again2': '333'}], 'shouldbeHere': true}
  var obj2 = {hello: '1',someArr:[{'hiagain': 123,'hiagain2': '333'}], someArr2:[{'apain': 123,'apain2': '333'}], 'shouldHere': false}

  
Example output for deepCompareTypeExistingKeys(obj1, obj2, []):

  [{
      "errorMsg":"Type MisMatch",
      "keyPath":"NonWorkingPayload.hello",
      "key":"hello",
      "WorkingPayloadValue":1,
      "NonWorkingPayloadValue":"1"
    },
    {
      "errorMsg":"Missing Key",
      "key":"again",
      "keyPath":"NonWorkingPayload.someArr2.again",
      "WorkingPayloadValue":123
    },
    {
      "errorMsg":"Missing Key",
      "key":"again2",
      "keyPath":"NonWorkingPayload.someArr2.again2",
      "WorkingPayloadValue":"333"
    },
    {
      "errorMsg":"Missing Key",
      "key":"shouldbeHere",
      "keyPath":"NonWorkingPayload.shouldbeHere",
      "WorkingPayloadValue":true
    }]
  
Example output for deepCompareTypeExistingKeys(obj1, obj2, []):

  [{
    "errorMsg":"Type MisMatch"
    "keyPath":"NonWorkingPayload.hello"
    "key":"hello"
    "WorkingPayloadValue":"1"
    "NonWorkingPayloadValue":1
  },
  {
    "errorMsg":"Missing Key"
    "key":"apain"
    "keyPath":"NonWorkingPayload.someArr2.apain"
    "WorkingPayloadValue":123
  },
  {
    "errorMsg":"Missing Key"
    "key":"apain2"
    "keyPath":"NonWorkingPayload.someArr2.apain2"
    "WorkingPayloadValue":"333"
  },
  {
    "errorMsg":"Missing Key"
    "key":"shouldHere"
    "keyPath":"NonWorkingPayload.shouldHere"
    "WorkingPayloadValue":false
  }]