1

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

Priyanga
1431 gold badge3 silver badges16 bronze badges
asked Dec 3, 2008 at 16:30

6 Answers 6

2

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
answered Dec 3, 2008 at 17:29
Sign up to request clarification or add additional context in comments.

Comments

1

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.

answered Dec 3, 2008 at 16:39

3 Comments

Ouch! I guess I am going to be coding server side then - I refuse to use regex's
That's a ridiculous thing to say and you deserve hours of hard coding pain to teach you a lesson.
Hi Adam! haha - I've had to use them more then often to realize to avoid them wherever possible ;-)
1

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);
});
answered Apr 25, 2010 at 0:38

Comments

0

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.

answered Dec 3, 2008 at 16:56

Comments

0

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>
answered Dec 3, 2008 at 22:58

Comments

0

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+')');
answered Dec 9, 2008 at 23:08

2 Comments

This fails with the following example: {foo:'sometext', bar:'more}{text'}{moo:'another string'} Because it would insert a comma into a string.
You said in the question that you tried to split on }{, so I assumed that you do not have }{ in your values...

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.