I'm looking to reduce storage requirements for JSON data by deltifying it against a known set of defaults. Basically, what I want is an inverse for jQuery's .extend()
function, such that the following test passes for arbitrary JSON-compatible objects:
function test_delta(defaults, delta) {
var current = $.extend(true, {}, defaults, delta);
QUnit.same(get_delta(current, defaults), delta);
}
Before I start writing my own get_delta()
, is anyone aware of an existing implementation?
jQuery | extend() method This extend() Method in jQuery is used to merge the contents of two or more objects together into the first object.
The extends keyword is used in class declarations or class expressions to create a class that is a child of another class.
The extends keyword can be used to extend the objects as well as classes in JavaScript. It is usually used to create a class which is child of another class. Syntax: class childclass extends parentclass {...}
What you're really looking for is an object diff(erential) algorithm.
Not too difficult to write -
function diff (obj1, obj2) {
var delta = {};
for (var x in obj1) {
if (obj2.hasOwnProperty(x)) {
if (typeof obj2[x] == "object") {
//recurse nested objects/arrays
delta[x] = diff(obj1[x], obj2[x]);
}
else {
//if obj2 doesn't match then - modified attribute
if (obj2[x] != obj1[x]) {
delta[x] = obj1[x];
}
}
}
else {
//obj2 doesn't have this - new attribute
delta[x] = obj1[x];
}
}
return delta;
}
alert(
JSON.stringify(
diff({ hello : 'world', gone : 'fishing' },
{ hello : 'world' })
)
);
//outputs:
{ gone : 'fishing' }
As you can see this is a very basic implementation - you could extend this to provide a complete differential by returning additions to obj2 in a separate object.
This code isn't bug free, object protoypes and functions will be handled differently in different browsers, but it should suffice as a demonstration for data structures.
Try something like that:
jQuery.extend({
deltaExtend: function(deep, target, defaults, delta){
var result = jQuery.extend.apply(jQuery, arguments);
jQuery(result).data('delta', delta);
jQuery(result).data('defaults', defaults);
return result;
}
});
usage:
var result = $.deltaExtend(true, {}, defaults, delta);
$(result).data('delta') //returns delta object
$(result).data('defaults') //returns default object
It also can be tweaked to get it working for N objects, just requires a little more thinking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With