2012-02-23 11 views
7

Io lavoro su un'applicazione Web che riceve dati JSON con nomi di proprietà maiuscole. Ho bisogno che quei nomi di proprietà siano in minuscolo, quindi sto usando una funzione per ricorrere ricorsivamente attraverso l'oggetto JSON e convertirli in lettere minuscole.Ottimizzazione del codice JavaScript che mette in minuscolo i nomi di proprietà JSON

Il problema è che le mie risposte JSON possono diventare molto grandi. Voglio che la funzione funzioni bene anche se deve elaborare JSON con 60.000 nomi di proprietà e vari livelli di nidificazione.

La funzione lettere minuscole è:

FN = function (obj) 
{var ret = null; 
    if (typeof(obj) == "string" || typeof(obj) == "number") 
     return obj; 
    else if (obj.push) 
     ret = []; 
    else 
     ret = {}; 
    for (var key in obj) 
     ret[String(key).toLowerCase()] = FN(obj[key]); 
    return ret; 
}; 

E io l'esecuzione di alcune analisi comparativa qui: http://jsfiddle.net/emw89/7/

Gli orologi di prova di cui sopra in a ~ 570MS sulla mia macchina.

C'è qualcosa che posso fare per migliorare le prestazioni di questa funzione?

Modifica: ho chiuso il mio IE, ho riaperto IE e ho eseguito nuovamente il benchmark jsfiddle - ora è arrivato a ~ 180ms per me. Il mio IE era rimasto aperto per un paio di giorni consecutivi fino a quel momento, quindi forse questo è ciò che ha causato una performance così scarsa. Ad ogni modo, sono ancora interessato se c'è un modo per ottimizzare ulteriormente questa funzione. Ogni volta che il tempo trascorso in più per l'elaborazione di JSON aggiunge direttamente al tempo trascorso di ogni richiesta AJAX.

+1

compie intorno ~ 150 ms per me – JKirchartz

+0

78ms - IE9. Evviva per la CPU i7. Chrome sembra circa il 30% più lento. Tutta la spesa è nella ricorsione, quindi non sono sicuro che ci sia molto altro da fare. –

+0

Due parole: [Chrome Frame] (http://code.google.com/intl/de-DE/chrome/chromeframe/) –

risposta

5
var lowerCache = {}; 

FN = function (obj) 
{ 
    if (typeof(obj) === "string" || typeof(obj) === "number") 
     return obj; 

     var l = obj.length; 
    if (l) { 
     l |= 0; 
     var result = []; 
     result.length = l; 
     for (var i = 0; i < l; i++) { 
      var newVal = obj[i]; 
      result[i] = typeof(newVal) === "string" ? newVal : FN(newVal); 
     } 
     return result; 
    } else { 
    var ret = {}; 
    for (var key in obj) { 

     var keyStr = typeof(key) === "string" ? key : String(key); 
     var newKey = lowerCache[keyStr]; 
     if (newKey === undefined) { 
      newKey = keyStr.toLowerCase(); 
      lowerCache[keyStr] = newKey; 
     } 

     var newVal = obj[key]; 
     ret[newKey] = typeof(newVal) === "string" ? newVal : FN(newVal); 
    } 
    return ret; 
    } 
}; 

100% più veloce.

+1

hm ... se obj è array questo codice restituisce array vuoto, o mi sbaglio – komelgman

+0

@komelgman, grazie. Fisso. Le prestazioni rimangono. – usr

+0

Sembra il vincitore, ma lascerò la domanda senza risposta ancora per un po 'di tempo nel caso in cui un altro mago si accinga a qualcosa. –

3

Lo farei con la semplice regex replace.

  1. Usa JSON per convertire oggetto stringa
  2. Sostituire tutti gli oggetti con lo stesso nome proprio minuscolo nuovo
  3. stringa convertire in oggetto

esempio

var obj = { SENAD: "meskin" }; 

var str = JSON.stringify(obj); 

function lCase(xxx) 
{ 
    pattern = /\"([a-z0-9_-]{0,})\"\:/gi; 
    return xxx.replace(pattern, function() { return arguments[0].toLowerCase() }); 
} 
str = lCase(str); 

var newObj = JSON.parse(str); 
alert(newObj.senad); 
console.log(str); 

Spero che questo aiuti.

+0

+1 A seconda della complessità del JSON, penso che potrebbe essere preferibile. JSON è già una stringa, quindi dovresti essere in grado di saltare il passo 1 (che è il vantaggio rispetto all'altro metodo). – MrWhite

Problemi correlati