除非您愿意更改您的数据格式,或者您可以找到一种简单的方法在接收后将其转换为正确的 JSON,否则最好的选择是手动解析。
最简单的匹配器(假设“nice”值):
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
被解析器接受。
它允许转义顶级逗号。这可能不是错误:\,,\,
是一个有效的字符串,包含两个由一个未转义的逗号分隔的顶级转义逗号。
尾部反斜杠会产生意外的输出。同样,这将通过读取我们正在转义的数据来解决。一个更简单的解决方法是buffer += input[++i] || ''
(附加一个空字符串而不是undefined
,但这允许无效输入。
它允许各种其他无效输入:[""'']{'\\'}"a"
只是一个例子。修复需要更好(更复杂)的语法,以及相应的更复杂的解析器。
话虽如此,使用 JSON 传输数据不是更好吗?
选项 1:一个真实的对象:{"text":"firstName", "css":{
...
选项 2(仅当您真的希望时):一个字符串数组:["text:firstName, css:{
...
在这两种情况下,JSON.parse(input)
都是你的朋友。