views:

798

answers:

5

I'm using jQuery's ajax function to hit a cross domain url. The url will return json. I'm in the discovery phase with this but I think, because the json values contain several '&quot' strings, the json eval is throwing an error and stopping the execution of my client side script. The error that I get is "unterminated string literal". I know that if I hard-code the returned json by putting it in a local div and remove the '"' strings (and a couple of hidden special characters), I can get the json to eval successfully. Whether through work-around, or through a correction to my code, what can I do to get the json from the url and store it in my client side javascript as a valid json object?

my current code. none of the defined functions (success, complete, error, dataFilter) execute:

$(function() {
  $.ajax({
  url: "http://www.codemash.org/rest/sessions.json?format=jsonp&callback=?", 
  dataType: "jsonp",
  success: successFunc,
  complete: completeFunc,
  error: errorFunc,
  dataFilter: dataFilterFunc
});

});

function successFunc() { console.log('successFunc(). enter.'); }
function completeFunc() { console.log('complete(). enter.'); }
function errorFunc() { console.log('errorFunc(). enter.'); }
function dataFilterFunc(data, type) { 
  data.replace(/\W/g, ' ');
  return data; 
}
+1  A: 

Hmm. I don't know jQuery, but I know JSON. (I wrote a C++ based parser for it.) I went to the url you show: http://www.codemash.org/rest/sessions.json?format=jsonp&callback=?. Python's JSON parser accepts that, and my experience is that Python's JSON parser is correct. Note that this:

{ "blah": "string " More more more" }

...is valid JSON. The " part gets no special interpretation in JSON - they are just characters in the string.


Edit: Looking harder at this, I find it very interesting that whatever is generating this is escaping some forward slashes, but not all. The "Start" items are "\/Date(-XXXXX)\/", which is the text /Date(-XXXXX)/ - / in JSON can optionally be escaped. However, in items with keys "SpeakerURI" and "URI", they are not escaped.


Edit: Ran this through my C++ based parser. Initially it did not take it, but this JSON actually exposed a bug in my parser.

Thanatos
It's an MS convention for serializing .NET `DateTime` objects: http://msdn.microsoft.com/en-us/library/bb299886(loband).aspx#intro_to_json_sidebarb
Crescent Fresh
A: 

You might consider trying the jquery-jsponp plugin, which fixes some problems with jQuery's jsonp handling.

http://code.google.com/p/jquery-jsonp/

I use it and there are a lot of great examples.

You really need to get your callbacks working so you can see what's going on.


Update: I took a stab with jsonp and I'm getting unexpected token errors. Not sure why--I can grab the data manually from the URL, assign it to a JavaScript variable in the console, and it's just fine.

Nosredna
Does it say where in the JSON? If you need something with line breaks, I put one here: http://pastebin.com/m65681d28 -- this looks like a bug in the JSON parser.
Thanatos
Sorry. No time to trace tonight. Maybe tomorrow.
Nosredna
I also had to modify line 250 in pastbin.com/m65681d28 for the json to parse. If I remember correctly, I had to replace the 'spaces' after "Level:" and "Duration:". I'll verify tomorrow.
mark
+1  A: 

The problem is the JSONP service, it is dismissing completely the callback parameter.

A JSONP response is simply a function call using the callback get parameter as the function name:

If you look the response of some JSONP service, it should be like this:

http://somesite.com/jsonp?callback=myCallback

Would return:

myCallback({/*json*/});

While the one you post is returning plain valid JSON, but it cannot be handled as a JSONP response.

CMS
Ooh, the JSON lint link is valuable, thank you.
Thanatos
Yup. That's it. Good catch.
Nosredna
A: 

Hi,

After analyzing your data on an hour,

I found following

{
   "URI":"/rest/sessions/Maintainable-ASPNET-MVC",
   "Title":"Maintainable ASP.NET MVC",
   "Abstract":".....\u003e\u2028Duration: 60-90 minutes\u003cbr\u003e\u2028Subject Area: development....."
}

There is char \u2028 before Duration, and Subject Area,

\u2028 is line seperator, so Its mean, kind of \n, so you have line break between the quotes "", that may be root case.

If you remove that, You wont see unterminated string literal in firebug.

To test that, paste following in address bar, Firefox and Opera fails, while IE8 and Chrome is working

javascript:alert(eval('[{"Abstract":"\u003e
    Duration: 60-90 minutes\u003cbr\u003e
    Subject Area: development."}]'))

somebody blogged about that already

http://bulknews.typepad.com/blog/2009/02/json-jquery-and-some-unicode-characters-u2028.html

S.Mark
Nope -- that is valid UTF-8: it is U-2028, which is a line separator. Your decode failed because you typed it in wrong. It does not affect the validity of the JSON text.
Thanatos
And what update did you make? The presence of a U+2028 within a JSON string is valid JSON.
Thanatos
Offset 0x62E1 within the JSON text is where you're looking, correct?
Thanatos
No, the real character is just fine. See the JSON RFC: http://www.ietf.org/rfc/rfc4627.txt -- specifically, note: `unescaped = %x20-21 / %x23-5B / %x5D-10FFFF` - since U+2028 is within the ranges given, a JSON parser should accept U+2028 encoded directly, or escaped as \u2028.
Thanatos
All browser have its own implementation, I have added code to test that, firefox, and Opera fails, while IE8 and Chrome is working
S.Mark
A: 

I don't appear to be any closer to a client side solution. I changed the code to use jQuery-jsonp. It now looks like this:

$(function() {
  $.jsonp({
  url: "http://www.codemash.org/rest/sessions.json?format=jsonp&callback=?", 
  async: false,
  dataType: "jsonp",
  success: successFunc,
  complete: completeFunc,
  error: errorFunc,
  dataFilter: dataFilterFunc
});

});

function successFunc(json, textStatus) { 
  console.log('successFunc(). enter.'); 
}
function completeFunc(xOptions, textStatus) { 
  console.log('complete(). textStatus: ['+textStatus + ']'); 
}
function errorFunc(xOptions, textStatus) { 
  console.log('errorFunc(). textStatus: [' + textStatus + ']'); 
}
function dataFilterFunc(j) { 
  console.log('dataFilterFunc(). enter.');
  return j; 
}

Firebug's console log displays:

X unterminated string literal
[{"URI"..... ( the json returned from the server
errorFunc(). textStatus: [error]
complete(). textStatus: [error]

For whatever reason, the json parse in my Firefox browser (FF v3.0.15, Linux Ubuntu 9.0.4) is throwing the "unterminated string literal" exception. I know if I remove the '& q u o t' strings and two characters in the 'Maintainable ASP.NET MVC' block then the json will parse successfully. Since I have no control on the server side, is there any thing I can do with client-side javascript that will eventually get the server's json string, as-is, into a client side json object. I thought the dataFilter property for jsonp was set up exactly for that purpose, to intercept the json and 'scrub' it. However, that function in my code is not called, quite possibly because the json that is passed into the dataFilterFunc function will not parse successfully.

mark