2010-08-24 10 views
16

मेरे पास एक बहुत बड़ी JSON स्ट्रिंग है जिसे मुझे ब्राउज़र ब्राउज़र में पार्स करने की आवश्यकता है। अभी, कुछ ब्राउज़रों में, मैं स्टैक स्पेस से बाहर चला गया। दुर्भाग्यवश, मेरे JSON में उपयोगकर्ता स्ट्रिंग्स हो सकते हैं, इसलिए मैं eval का उपयोग नहीं कर सकता या अन्यथा ब्राउज़र को इसका विश्लेषण नहीं कर सकता।गैर-पुनरावर्ती जावास्क्रिप्ट JSON पार्सर

मैंने कुछ मानक जावास्क्रिप्ट JSON पार्सर्स को देखा है, और वे रिकर्सिव हैं। आश्चर्य है कि अगर कोई भी किसी भी JSON पार्सर के बारे में जानता है जो सुरक्षित और गैर-पुनरावर्ती है। मैं इसके लिए कम सुविधाओं के लिए तैयार रहूंगा - मेरे पास बस वस्तुओं की एक विशाल सरणी है।

वैकल्पिक रूप से, अगर कोई ऐसे व्यक्ति को जानता है जो संशोधित करना आसान हो सकता है, तो यह भी एक बड़ी मदद होगी।

संपादित करें: निकट निरीक्षण पर स्टैक्स ओवरफ़्लो को पार्सर के अंदर उपयोग किए जाने वाले eval() द्वारा फेंक दिया जाता है। तो, यह रिकर्सिव होना चाहिए।

+0

अच्छी तरह से, दोबारा घोंसले वाली संरचना को पार्स करने के लिए, एक बार फिर से एक ही प्रक्रिया के माध्यम से जाना पड़ता है। क्या आप वाकई संरचना वास्तव में मान्य हैं? "बहुत बड़ा" कितना बड़ा है? – Pointy

+0

यह कानूनी है - यह कुछ हजार वस्तुओं की एक सरणी है। जब यह एक निश्चित आकार में आता है, eval() इसे पार्स नहीं कर सकता (ठीक है, आईई कर सकता है, लेकिन अन्य ब्राउज़र नहीं कर सकते हैं) –

+0

@ पॉइंट हां यह एक ही प्रक्रिया के माध्यम से जाएगा, लेकिन इसे उपयोग करने की आवश्यकता नहीं है ढेर, जो अंतरिक्ष से बाहर हो सकता है।संभवतः, एक गैर-पुनरावर्ती व्यक्ति ढेर में कुछ अन्य समतुल्य डेटा-संरचना बनाता है (जो बड़ा है, उम्मीद है) –

उत्तर

0

ब्राउज़र में जेएसओएन पार्सिंग आमतौर पर केवल eval के साथ किया जाता है, लेकिन एक नियमित अभिव्यक्ति "लिंट" के साथ eval से पहले, यह JSON का मूल्यांकन करने के लिए सुरक्षित बनाने के लिए माना जाता है।

विकिपीडिया पर इस पर एक उदाहरण है:

+1

सही है, अब मैं देखता हूं कि सुरक्षा की जांच के बाद eval को बुलाया जा रहा है, और फिर यह एक ढेर ओवरफ्लो फेंकता है (क्योंकि यह आंतरिक रूप से रिकर्सिव है और JSON स्ट्रिंग बड़ा है) –

+0

धन्यवाद - आपके सुझाव ने मुझे वास्तविक समस्या को eval() में देखने में मदद की। –

5

eval stackoverflow फेंकता है, तो आप इस

http://code.google.com/p/json-sans-eval/

एक JSON पार्सर कि 'नहीं करता है का उपयोग कर सकते eval() बिल्कुल उपयोग नहीं करते हैं।

1

मैं आपको JSON स्ट्रिंग को खंडों में विभाजित करने की सलाह देता हूं, और उन्हें मांग पर लाता हूं। AJAX का भी उपयोग कर सकते हैं, आप एक नुस्खा ले सकते हैं जो आपकी आवश्यकताओं के अनुरूप है। "विभाजन और जीत" तंत्र का उपयोग करके, मुझे लगता है कि आप अभी भी सामान्य JSON पार्सिंग विधियों का उपयोग कर सकते हैं।

आशा है कि मदद करता है,

+0

हमने इसे माना, लेकिन अन्य बाधाओं को मुश्किल करना मुश्किल है। हमें सभी को एक बार में प्रतिक्रिया भेजने की जरूरत है। इसे सीमित करने के लिए ताकि एक विभाजन() काम करेगा, एक और भागने की आवश्यकता है। हम अभी भी इस तरह से जा सकते हैं, लेकिन एक बेहतर पार्सर खोजने की उम्मीद कर रहे हैं। –

3

मैं json पारसर्स कि कई भाषाओं में पुनरावर्ती नहीं हैं लिखा है, लेकिन अब जावास्क्रिप्ट में नहीं है जब तक। रिकर्सिव होने के बजाय, यह स्टैक नामक स्थानीय सरणी का उपयोग करता है। क्रियालेखन में यह काफी तेजी से और रिकर्सन से अधिक स्मृति कुशल था, और मुझे लगता है कि जावास्क्रिप्ट समान होगा।

यह कार्यान्वयन केवल eval का उपयोग बैकस्लैश एस्केप के साथ उद्धृत तारों के लिए करता है, दोनों अनुकूलन और सरलीकरण के रूप में। इसे किसी भी अन्य पार्सर से स्ट्रिंग हैंडलिंग के साथ आसानी से बदला जा सकता है। एस्केप हैंडलिंग कोड लंबा है और रिकर्सन से संबंधित नहीं है।

यह कार्यान्वयन निम्नलिखित तरीकों से सख्त नहीं है (कम से कम)। यह व्हाइट्स के रूप में 8 बिट वर्णों का इलाज करता है। यह संख्याओं में अग्रणी "+" और "0" की अनुमति देता है। यह सरणी और वस्तुओं में पीछे "," की अनुमति देता है। यह पहले परिणाम के बाद इनपुट को अनदेखा करता है। तो "[+0 9,] 2" रिटर्न [9] और "2" को अनदेखा करता है।

function parseJSON(inJSON) { 
    var result; 
    var parent; 
    var string; 

    var depth = 0; 
    var stack = new Array(); 
    var state = 0; 

    var began , place = 0 , limit = inJSON.length; 
    var letter; 

    while (place < limit) { 
     letter = inJSON.charCodeAt(place++); 

     if (letter <= 0x20 || letter >= 0x7F) { // whitespace or control 
     } else if (letter === 0x22) {    // " string 
      var slash = 0; 
      var plain = true; 

      began = place - 1; 
      while (place < limit) { 
       letter = inJSON.charCodeAt(place++); 

       if (slash !== 0) { 
        slash = 0; 
       } else if (letter === 0x5C) {  // \ escape 
        slash = 1; 
        plain = false; 
       } else if (letter === 0x22) {  // " string 
        if (plain) { 
         result = inJSON.substring(began + 1 , place - 1); 
        } else { 
         string = inJSON.substring(began , place); 
         result = eval(string); // eval to unescape 
        } 

        break; 
       } 
      } 
     } else if (letter === 0x7B) {    // { object 
      stack[depth++] = state; 
      stack[depth++] = parent; 
      parent = new Object(); 
      result = undefined; 
      state = letter; 
     } else if (letter === 0x7D) {    // } object 
      if (state === 0x3A) { 
       parent[stack[--depth]] = result; 
       state = stack[--depth]; 
      } 

      if (state === 0x7B) { 
       result = parent; 
       parent = stack[--depth]; 
       state = stack[--depth]; 
      } else { 
       // error got } expected state { 
       result = undefined; 
       break; 
      } 
     } else if (letter === 0x5B) {    // [ array 
      stack[depth++] = state; 
      stack[depth++] = parent; 
      parent = new Array(); 
      result = undefined; 
      state = letter; 
     } else if (letter === 0x5D) {    // ] array 
      if (state === 0x5B) { 
       if (undefined !== result) parent.push(result); 

       result = parent; 
       parent = stack[--depth]; 
       state = stack[--depth]; 
      } else { 
       // error got ] expected state [ 
       result = undefined; 
       break; 
      } 
     } else if (letter === 0x2C) {    // , delimiter 
      if (undefined === result) { 
       // error got , expected previous value 
       break; 
      } else if (state === 0x3A) { 
       parent[stack[--depth]] = result; 
       state = stack[--depth]; 
       result = undefined; 
      } else if (state === 0x5B) { 
       parent.push(result); 
       result = undefined; 
      } else { 
       // error got , expected state [ or : 
       result = undefined; 
       break; 
      } 
     } else if (letter === 0x3A) {    // : assignment 
      if (state === 0x7B) { 
       // could verify result is string 
       stack[depth++] = state; 
       stack[depth++] = result; 
       state = letter; 
       result = undefined; 
      } else { 
       // error got : expected state { 
       result = undefined; 
       break; 
      } 
     } else { 
      if ((letter >= 0x30 && letter <= 0x39) || letter === 0x2B || letter === 0x2D || letter === 0x2E) { 
       var    exponent = -2; 
       var    real = (letter === 0x2E); 
       var    digits = (letter >= 0x30 && letter <= 0x39) ? 1 : 0; 

       began = place - 1; 
       while (place < limit) { 
        letter = inJSON.charCodeAt(place++); 

        if (letter >= 0x30 && letter <= 0x39) {   // digit 
         digits += 1; 
        } else if (letter === 0x2E) {      // . 
         if (real) break; 
         else real = true; 
        } else if (letter === 0x45 || letter === 0x65) { // e E 
         if (exponent > began || 0 === digits) break; 
         else exponent = place - 1; 
         real = true; 
        } else if (letter === 0x2B || letter === 0x2D) { // + - 
         if (place != exponent + 2) break; 
        } else { 
         break; 
        } 
       } 

       place -= 1; 
       string = inJSON.substring(began , place); 

       if (0 === digits) break; // error expected digits 
       if (real) result = parseFloat(string); 
       else result = parseInt(string , 10); 
      } else if (letter === 0x6E && 'ull' === inJSON.substr(place , 3)) { 
       result = null; 
       place += 3; 
      } else if (letter === 0x74 && 'rue' === inJSON.substr(place , 3)) { 
       result = true; 
       place += 3; 
      } else if (letter === 0x66 && 'alse' === inJSON.substr(place , 4)) { 
       result = false; 
       place += 4; 
      } else { 
       // error unrecognized literal 
       result = undefined; 
       break; 
      } 
     } 

     if (0 === depth) break; 
    } 

    return result; 
} 
संबंधित मुद्दे