2012-05-03 69 views
-4

我正在創建基於JSON和JavaScript的DSL,並且我要求將鍵值指定爲'原始'並且不包含在字符串分隔符中。一個簡單的例子是希望解釋這一點:在解析到對象之前手動解析JSON

{myKey:custom_function('arg1'), myKey2:custom_function("another arg1")} 

應該成爲

{myKey:"custom_function('arg1')", myKey2:"custom_function(\"another arg1\")"} 

這是因爲在解析JSON對象時,custom_function將不存在。我需要能夠解析JSON而無需評估任何值,然後只在迭代密鑰時逐個擴展值。

可以使用什麼正則表達式或其他方法將第一個片段轉換爲第二個片段?

我假設一個更簡單的解決方案將覆蓋90%的案例,但是編寫一個防彈實施需要花費很大的精力。基於我對JavaScript的正則表達式支持的研究(顯然沒有lookbehind功能),我假設它需要的不僅僅是1或2行的正則表達式模式。

此外,這是一個節點應用程序,所以它的任何技巧也將有所幫助。

編輯:

這個問題似乎得到一些downvotes,但我已經離開它,無論如何,未來的Google /我自己參考的利益。這是關於什麼方法/技術將工作最適合這樣的問題,而且有可能很容易地面對誰的類似問題的其他節點/ JS新人一個完全有效的問題。

+0

我很抱歉,但是,什麼是DSL? –

+0

域名特定語言。這是一個複雜的商業案例,用戶有一項功能可以讓他們編寫腳本來指導應用程序。 – Trindaz

+0

我覺得downvotes是由於您的DSL是一個混合JSON樣機,不使那麼多的意義而不是隻使用JSON作爲您的DSL。與管理層的DSL應該僅僅是JSON標準爭論,點即是更容易維護,面向未來的,更容易實現,啦啦啦。 – balupton

回答

0

最終回答:正則表達式不適合這樣複雜的任務。我在網上找到的任何類似的複雜解決方案(例如,刪除代碼註釋)都採用主要定製的迭代方法,只是謹慎地使用正則表達式,所以類似的方法在這種情況下不會太無痛。

所以最終的「最佳」的方法,我能找到不涉及非常多的正則表達式或任何專業圖書館從節點或其他地方適合的問題。

最後,誰可能有類似的問題未來的Google的利益,我出版了我的解決方案在https://gist.github.com/2590689及以下複製:

//clothe a hub file that has 'naked' expressions 
//e.g. turn {key:$('body p')} into {key:"$('body p')"} 
function clothe(contents){ 

closers = /[\}\]\)\/"']/ 
openers = /[\{\[\(\/"']/ 
closing = { 
    "{": "}", 
    "[": "]", 
    "(": ")", 
    "/": "/", 
    '"': '"', 
    "'": "'" 
} 

contents = contents.split(""); 

var beforeKey = true; 
var inKey = false; 
var beforeValue = false; 
var inValue = false; 
var inArray = false; 
var delimiterStack = []; 

function inDelimited(){ 
    return delimiterStack.length > 0; 
} 

function toggleDelimiter(d){ 
    if(openers.exec(d) && !closers.exec(d)){ 
     pushDelimiter(d); 
    }else if(openers.exec(d) && closers.exec(d)){ 
     if(topDelimiter()){ 
      if(topDelimiter()==d){ 
       popDelimiterIfValid(d); 
      }else{ 
       pushDelimiter(d); 
      } 
     }else{ 
      pushDelimiter(d); 
     } 
    }else if(closers.exec(d)){ 
     popDelimiterIfValid(d); 
    } 
} 

function topDelimiter(){ 
    if(delimiterStack.length>=0){ 
     return delimiterStack[delimiterStack.length-1]; 
    }else{ 
     return undefined; 
    } 
} 

function pushDelimiter(d){ 
    delimiterStack.push(d); 
} 

function popDelimiterIfValid(d){ 
    if(delimiterStack.length>0) 
     if(closing[delimiterStack[delimiterStack.length-1]]==d) 
      delimiterStack.pop(d); 
} 

function rTrimmedRightBound(rightBound){ 
    while(rightBound>0){ 
     if(!/\s/g.exec(contents[--rightBound])){ 
      return rightBound+1; 
     } 
    } 
} 

for(var i=0; i<contents.length; i++){ 

    function delimiterCheck(c){ 
     if(c=='"'){ 
      toggleDelimiter('"'); 
      contents.splice(i, 0, '\\'); 
      i++; 
     }else if(openers.exec(c) || closers.exec(c)){ 
      toggleDelimiter(c) 
     } 
    } 

    if(beforeKey){ 
     if(/[a-zA-Z0-9$_!]/.exec(contents[i])){ 
      beforeKey = false; 
      inKey = true; 
     } 
    }else if(inKey){ 
     if(contents[i]==":"){ 
      inKey = false; 
      beforeValue = true; 
     } 
    }else if(beforeValue){ 
     if(/[a-zA-Z0-9$_!'"\(\/]/.exec(contents[i])){ 
      contents.splice(i, 0, '"'); 
      i++; 
      beforeValue = false; 
      inValue = true; 
      delimiterCheck(contents[i]); 
     }else if(/\{/.exec(contents[i])){ 
      beforeKey = true; 
      beforeValue = false; 
     }else if(/\[/.exec(contents[i])){ 
      beforeValue = false; 
      inArray = true; 
     } 
    }else if(inArray && !inValue){ 
     if(/[a-zA-Z0-9$_!'"\(\/]/.exec(contents[i])){ 
      contents.splice(i, 0, '"'); 
      i++; 
      beforeValue = false; 
      inValue = true; 
      delimiterCheck(contents[i]); 
     } 
    }else if(inValue){ 
     if(!inDelimited() && /[\},\]]/.exec(contents[i])){ 
      contents.splice(rTrimmedRightBound(i), 0, '"'); 
      i++; 
      inValue = false; 
      if(/\]/.exec(contents[i])){ 
       inArray = false; 
      } 
      beforeKey = !inArray; 
     }else{ 
      delimiterCheck(contents[i]); 
     } 
    } 
} 

return contents.join(""); 
}