2012-05-03 15 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を解析できるようにする必要があります。次に、キーを繰り返しながら値を1つずつ展開します。

第1のスニペットを第2のスニペットに切り替えるために使用できる正規表現やその他の方法はありますか?

私は単純な解決策がケースの90%をカバーすると仮定していますが、防弾実装の作成には多大な労力が必要です。私はJavaScriptの正規表現のサポート(確かにlookbehind機能はありません)に行った研究に基づいて、ちょうど1,2行以上の正規表現パターン以上のものを必要とすると仮定しています。

また、これはノードアプリケーションのためのものであり、このために持っているすべてのトリックも役に立ちます。

EDIT:

この質問は、いくつかのdownvotesを取得しているようだが、私は将来のGoogler /私自身の参照の利益のために、とにかくそれを残してきました。これはどのような方法/技術がこの種の問題に最も適しているかについての完全に有効な質問であり、同様の問題に直面している他のノード/ jsの新規参入者が容易に存在する可能性があります。

+0

ごめんなさい。しかし、DSLは何ですか? –

+0

ドメイン固有言語。これは複雑なビジネスケースのため、ユーザーがアプリケーションに指示するためのスクリプトを書くことができる機能を持っています。 – Trindaz

+0

DSLがハイブリッドJSONモックアップであることが原因でダウンボントが発生していると感じます。 DSLは単にJSON標準でなければならないという経営陣の主張によれば、ポイントはより保守性が高く、将来的に実現しやすく、ララララです。 – balupton

答えて

0

最終回答:Regexはこのような複雑なタスクには適していません。オンラインで見つけた同様の複雑な解決策(コードコメントの削除など)はすべて、主にカスタムの反復的なアプローチに頼っていましたが、あまり使用しないでください。

最終的に私が見つけることができる「最良の」方法は、非常に多くの正規表現やノードからの特殊なライブラリや、問題に適した別のライブラリを必要としませんでした。

最後に、同様の問題がある可能性があります将来のGooglerの利益のために、私は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(""); 
}