可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Due to the way my serverside script outputs I receive multiple JSON objects. {jsonhere}{jsonhere1}{jsonhere2}{jsonhere3} etc.. They aren't seperated by anything. If I would do a split based }{ I would lose those brackets. So is there an outerloop I can put over the regular $.each loop to make this work?
Thank you,
Ice
回答1:
Rough algorithm:
Define a stack Define an array LOOP on each character in the string IF the top item of the stack is a single or double quote THEN LOOP through each character until you find a matching single or double quote, then pop it from the stack. ELSE IF "{", push onto the stack IF "}" THEN pop a "{" from the stack if it is on top IF the stack is empty THEN //we just finished a full json object Throw this json object into an array for later consumption END IF END IF IF single-quote, push onto the stack IF double-quote, push onto the stack END IF END LOOP
回答2:
this isn't JSON.
jQuery interprets JSON the lazy way, calling eval() and hoping there's no 'real' code in there; therefore it won't accept that. (i guess you already know this).
it seems your only way out is to treat it as a text string, and use regular expressions to extract the data.
回答3:
The following would be a valid JSON response:
[ {JSON}, {JSON}, {JSON}, {JSON} ]
Since your JSON is malformed, simply fix it on the server side. The following code is a bit more brief than what EndangeredMassa suggested and it avoids adding a comma in between braces enclosed in quotes. I'm not so good at RegEx to figure it out with a single .replace().
var string = "{\"key\":\"val}{ue\"}{'key':'val}{ue'}{ \"asdf\" : 500 }"; var result = string.match(/('.*?')|(".*?")|(\d+)|({)|(:)|(})/g); var newstring = ""; for (var i in result) { var next = parseInt(i) + 1; if (next <= result.length) { if (result[i] == "}" && result[next] == "{") { newstring += "},"; } else { newstring += result[i]; } }
}
To loop through the JSON objects use the following:
$.each(eval(newstring), function() { //code that uses the JSON values alert(this.value1); alert(this.value2); });
回答4:
Unless you can guarantee that any strings in the data will not contain "}{", you can't even safely split it without parsing the JSON at least enough to keep track of whether you are in a string or not. For example if you just split this:
{"foo": "}{", "bar": 42}
around "}{", you would end get two invalid JSON objects instead of one.
If you know that can never happen, you could split around the braces and append "}" to each element except the last one, and prepend "{" to the last element. I would only do that if there was absolutely no other way though, because it's really fragile.
回答5:
I managed to cobble together a working example! Save the following text as an html page. It appears to work well in IE7 and FF3. Let me know if you have any trouble with it.
(I used jquery, but it's really not necessary at all.)
<html> <head> <script type="text/javascript" src="jquery-1.2.6.js"></script> <script type="text/javascript"> function handleClick() { var jsonStrs = parse(); var jsonObjs = []; for(var j=0;j<jsonStrs.length;j++) jsonObjs.push( parseJSON(jsonStrs[j]) ); //jsonObjs now contains an array of json objects document.getElementById('log').innerHTML = ''; displayResults(jsonObjs); } function displayResults(jsonObjs) { for(var k=0; k<jsonObjs.length; k++) { ShowObjProperties(jsonObjs[k]); } } function ShowObjProperties(obj) { var property, propCollection = ""; for(property in obj) { propCollection += (property + ": " + obj[property] + "<br>"); } log(propCollection); } function parseJSON(str) { var x_result = null; eval('x_result = ' + str); return x_result; } function parse() { //Setup var out = $('#output'); var rawinput = $('#inputtext').val(); var input = rawinput.split(''); var stack = []; stack.top = function() { if (this.length == 0) return null; return this[this.length-1]; } var jsonStrs = []; //Main Loop var ch = ''; var top = ''; var cursor = 0; var i = 0; while (i<input.length) { //Current Character ch = input[i]; top = stack.top(); if(top == "'" || top == '"') { //Ignore the rest of the string //You can add validation for possible unsafe javascript inside a string, here. ch = input[++i]; while(ch != top) { i++; if(i>=input.length) { alert('malformed string'); break; } ch = input[i]; } stack.pop(); } else { //You can add validation for unsafe javascript here. if(ch == ' ') { i++; continue; // Ignore spaces } if(ch == "{" || ch == "'" || ch == '"') stack.push(ch); if(ch == "}") { if(top=="{") { stack.pop(); } else { alert('malformed string'); break; } if(stack.length == 0) { var str = rawinput.substring(cursor, i+1) jsonStrs.push(str); cursor = i+1; } } } i++; } return jsonStrs; } function log(msg) { document.getElementById('log').innerHTML += msg + '<br>'; } </script> </head> <body> <textarea id="inputtext" rows="5" cols="40" style="overflow:auto">{foo:'bar'}</textarea><br> <button id="btnParse" onclick="handleClick();">Parse!</button><br /><br /> <div id="output"> </div> <b>Results:</b> <div id="log"></div> </body> </html>
回答6:
This is not JSON, on the client side just fix your JSON code and you can 'eval' it safely.
var jsonWrong = '{a:1}{a:2}{a:3}'; var jsonRight = jsonWrong.replace('}{', '},{'); var json = eval('('+jsonRight+')');