Forum Discussion

kmiesse's avatar
kmiesse
Contributor
8 years ago

JSON Object Diff

Is there a way to easily show what key values do not match between two JSON objects? If I have two objects with the same keys, can I output just the keys and values that do not match between the two objects? I am looking for a way to do this without having to create an equality expression for each key.

10 Replies

    • kmiesse's avatar
      kmiesse
      Contributor

      I think the Diff snap is for comparing streams of documents and not specifically two documents or two objects in a document. I know I can easily tell if the two objects differ but I want to be able to easily tell what key values or fields differ within the two objects. If two key names are the same but their values are not then the key name and differing values would be in the output document. I’m not sure how to do that without a comparison expression for each key/field, which is tedious and not self-maintained if the keys/fields of the objects change.

      • Piyush's avatar
        Piyush
        New Contributor III

        Can you provide some sample data on what are we trying to achieve here.

  • CMeyers's avatar
    CMeyers
    New Contributor II

    I have code that can do this in javascript, although for arrays it is checking differences by index so you would need to be aware of that. I would think this code snippet could be adapted to run in a script snap and get the output you desire. I put in the two objects from your example into the little utility code I had and it found the differences, would just need to modify the output formatting to what you specified.

    Function -

    self.internalFindDifference = function(obj1, obj2, parent, accum) {
        var result = accum || { "changes": [] };
                    
        for (key in obj1) {
            if (!obj2.hasOwnProperty(key)) {
                result.changes.push({ "field": parent ? parent + "." + key : key, "type": "add", "value": obj1[key] });                       
            } else if (!_.isEqual(obj1[key],obj2[key]) && typeof obj1[key] == 'object' && typeof obj2[key] == 'object') {
                var newParent = parent ? parent + "." + key : key;
                arguments.callee(obj1[key], obj2[key], newParent, result);
            } else if (!_.isEqual(obj1[key], obj2[key])) {
                result.changes.push({ "field": parent ? parent + "." + key : key, "type": "change", "fromValue": obj2[key], "toValue": obj1[key] });
            }
        }
                    
        for (key in obj2) {
            if (!obj1.hasOwnProperty(key)) {
                result.changes.push({ "field": parent ? parent + "." + key : key, "type": "delete", "fromValue": obj2[key] });                        
            }
        }
    
        return result;
    }
    

    Example calling code -

    var result = self.internalFindDifference(obj1, obj2, null, null);
    Console.log(JSON.stringify(result, null, 4));
    
    • kmiesse's avatar
      kmiesse
      Contributor

      Thank you! I was hoping there was a way to do this without scripting since it seems like a common use case for SnapLogic but I will have to give it a try!

      • nganapathiraju's avatar
        nganapathiraju
        Former Employee

        It is not a common usage. Deep level object nesting and comparison within those depths is a very uncommon scenario.