データ形式を変更する意思がない場合、または受信後にデータ形式を適切なJSONに変換する簡単な方法が見つからない場合を除いて、最善の策は手動で解析することです。
最も単純なマッチャー(「適切な」値を想定):
On ([{ - increment parens
On )]} - decrement parens or emit error if parens is zero
On , - emit and reset the buffer if parens is zero (finish a match)
If not , - push into the output buffer
これは「醜い」文字列(引用符で囲まれた引用符、エスケープされた引用符、エスケープされたエスケープなど)では機能しません。このパーサーは、比較的単純でありながら、すべての有効な入力を正しく解析する必要があります。
On ([{ - increment parens if the state is "start". Push to buffer.
On )]} - decrement parens if the state is "start" and parens is positive.
Emit an error if parens is zero. Push to buffer.
On , - emit and reset the buffer if parens is zero and the state is "start"
(finish a match). Push to buffer.
On \ - Push to buffer, and push and read the next symbol as well.
On ' - If the state is "start", change the state to "squote", and vice versa.
Push to buffer.
On " - If the state is "start", change the state to "dquote", and vice versa.
Push to buffer.
On EOF - Emit error if parens is not zero or the state is not "start".
これがJavascriptでの実装のスケッチです:
function splitLiteralBodyByCommas(input){
var out = [];
var iLen = input.length;
var parens = 0;
var state = "";
var buffer = ""; //using string for simplicity, but an array might be faster
for(var i=0; i<iLen; i++){
if(input[i] == ',' && !parens && !state){
out.push(buffer);
buffer = "";
}else{
buffer += input[i];
}
switch(input[i]){
case '(':
case '[':
case '{':
if(!state) parens++;
break;
case ')':
case ']':
case '}':
if(!state) if(!parens--)
throw new SyntaxError("closing paren, but no opening");
break;
case '"':
if(!state) state = '"';
else if(state === '"') state = '';
break;
case "'":
if(!state) state = "'";
else if(state === "'") state = '';
break;
case '\\':
buffer += input[++i];
break;
}//end of switch-input
}//end of for-input
if(state || parens)
throw new SyntaxError("unfinished input");
out.push(buffer);
return out;
}
このパーサーにはまだ欠点があります。
中かっこなどで親を閉じることができます。これを解決するにparens
は、シンボルのスタックを作成します。開始記号と終了記号が一致しない場合は、例外を発生させます。
不正な形式のUnicodeエスケープ文字列を許可します。\utest
パーサーによって受け入れられます。
最上位のコンマをエスケープできます。これはおそらく障害ではありません。これは\,,\,
有効な文字列であり、エスケープされていないコンマで区切られた2つのトップレベルのエスケープされたコンマが含まれています。
末尾の円記号は予期しない出力を生成します。繰り返しますが、これは、エスケープしているデータを読み取ることで修正されます。より簡単な修正はbuffer += input[++i] || ''
(の代わりに空の文字列を追加しますundefined
が、それは無効な入力を許可します。
それは他のあらゆる種類の無効な入力を許可します:[""'']{'\\'}"a"
単なる例です。修正には、より優れた(より複雑な)文法と、それに伴うより複雑なパーサーが必要になります。
そうは言っても、データの送信にはJSONを使用する方が良いのではないでしょうか。
オプション1:実際のオブジェクト:{"text":"firstName", "css":{
...オプション2(本当に
必要な場合のみ):文字列の配列:..。 ["text:firstName, css:{
どちらの場合も、JSON.parse(input)
あなたの友達です。