2010-08-04 5 views
7

Ich möchte die Speicheranforderungen für JSON-Daten reduzieren, indem ich sie gegen bekannte Standardwerte deletiere. Im Grunde, was ich will, ist ein inverse für jQuery .extend() Funktion, so dass der folgende Test bestanden wird für beliebige JSON-kompatible Objekte:Inverse von jQuery.extend (true, ...)

function test_delta(defaults, delta) { 
    var current = $.extend(true, {}, defaults, delta); 

    QUnit.same(get_delta(current, defaults), delta); 
} 

Bevor ich mit dem Schreiben beginne meine eigenen get_delta(), ist jemand bewusst eine bestehende Implementierung?

+0

Sie müssen selbst mit dem harten (Nested Loop) Weg umgehen. Wie du wahrscheinlich weißt. Es macht noch mehr Spaß, wenn Ihre JSON-Daten eine beliebige Tiefe haben. –

+0

Ja, ich habe schon einige interessante Randfälle gefunden; Deshalb dachte ich, ich würde das "SO-Orakel" fragen, bevor ich mich selbst damit beschäftige. Ah, gut. :-) –

+0

Ein guter Ausgangspunkt wäre die Funktion jQuery.fn.extend in [jQuery source] (http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js). – calvinf

Antwort

1

Was Sie wirklich suchen, ist ein Objekt Diff (Erential) -Algorithmus.

Nicht zu schwer zu schreiben -



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' } 

Wie Sie dies ist eine sehr einfache Implementierung sehen können - Sie diese erweitern könnte eine vollständige Differential zu schaffen, durch Ergänzungen der Rückkehr in ein separates Objekt obj2.

Dieser Code ist nicht fehlerfrei, Objektprototypen und Funktionen werden in verschiedenen Browsern unterschiedlich behandelt, sollten aber als Demonstration für Datenstrukturen ausreichen.

+0

Ich habe einen Stich gemacht, um meine eigene zu implementieren, aber es gab genug unklare Randfälle (besonders mit Arrays und gelöschten Eigenschaften), die wir entschieden haben, einfach die Datenbankspalte zu vergrößern. –

1

versuchen, etwas wie folgt aus:

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; 
    } 
}); 

Nutzung:

var result = $.deltaExtend(true, {}, defaults, delta); 
$(result).data('delta') //returns delta object 
$(result).data('defaults') //returns default object 

Es kann auch um es zu bekommen gezwickt arbeiten für N Objekte, erfordert nur ein wenig mehr denken.

+0

Das ist eine sehr interessante Idee! Leider wird '$ .extend' in meinem Fall nicht zum Erstellen des" Ergebnis "-Objekts verwendet. Dies galt für ein Portalsystem, bei dem jedes Portlet seine eigenen Standardeinstellungen definieren konnte. Die "aktuellen" Einstellungen würden dann über die Lebensdauer der Seite frei geändert werden, und als die Zeit gekommen war, den Portlet-Status zurück auf den Server zu speichern, hoffte ich, ein "Blind" -Delta durchzuführen, um die Speicheranforderungen zu reduzieren. –

+0

Ich habe eine andere Lösung im Hinterkopf, welche Browser unterstützen Sie und welche Versionen unterstützen Sie IE

1

Ich weiß, das ist ein bisschen spät, um relevant für das Thema Starter sein, aber Sie möchten vielleicht einen Blick auf die _.omit(object, *keys) Funktion von Underscore.js. Es macht genau das.

+0

Aber woher kennst du die 'Schlüssel'? – Bergi

+0

Die Schlüssel stammen von dem Objekt, in dem die Standardwerte gespeichert sind. '_.keys (defaultObject)' gibt Ihnen ein Array seiner Schlüssel. – oley

+0

Das hättest du vielleicht in deiner Antwort erwähnt ... Und beachte, dass diese Methode nur für * addierte * Eigenschaften funktioniert, nicht für alle * geänderten * Einsen. – Bergi