4

I stumbled upon this problem while helping another user here at SO, There is a webservice that sends a json formatted output, that when looked into the console seems ok but it triggers a parse error when parsing it directly using getJSON or a similar ajax request:

Unexpected token ':'. Parse error.

While this is weird, it could be solved by just getting the plain text instead, however the server needs a JSONP request (it has no CORS headers). I tried in many ways to prevent jQuery to automatically parse the response to JSON but to no avail. If anybody knows how to either fix the seemingly incorrect parse error or to prevent parsing in the first place, please let me know.

The code I have tried so far is:

var baseUrl = "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001440043/timeline?gameHash=4725b07311676885&callback=?";

$.ajax({

  url: baseUrl,
  dataType: 'json',
  crossDomain: true,
  processData: false,

  converters: {"* text": window.String, "text html": true, "text json": true, "text xml": jQuery.parseXML},
  success: function(data){

    $('#output').html(data);
  },
  error:function(jqXHR,status, error){
    console.log(jqXHR);
    console.log(status);
    console.log(error);
    $('#output').html(jqXHR);
  }
});

Jsfiddle: https://jsfiddle.net/6Lwjpjmo/22/

To make the question more clear:
When I use datatype json with callback in the url or datatype jsonp I can see in the console the json response being returned. But it triggers a parse error.
If instead I use datatype text or anything else I get a cross domain denied error.

Niki van Stein
  • 10,564
  • 3
  • 29
  • 62

2 Answers2

3

Change the dataType to text. Should leave it as a string for you to do what you like with it

var baseUrl = "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001440043/timeline?gameHash=4725b07311676885&callback=?";

$.ajax({

  url: baseUrl,
  dataType: 'text',
  crossDomain: true,
  processData: false,

  converters: {"* text": window.String, "text html": true, "text json": true, "text xml": jQuery.parseXML},
  success: function(data){

    $('#output').html(data);
  },
  error:function(jqXHR,status, error){
    console.log(jqXHR);
    console.log(status);
    console.log(error);
    $('#output').html(jqXHR);
  }
});
Ajwhiteway
  • 986
  • 1
  • 9
  • 23
  • Does not work.. did you check it yourself? It gives access origin error with this settings. I had tried it myself as well. – Niki van Stein Dec 10 '15 at 16:59
  • 1
    I've used it before, did not set up a new instance to check it. What precisely is the error? When I hear origin error I think cross domain access which you have-to specifically allow. – Ajwhiteway Dec 10 '15 at 17:02
  • That is the point... with JSONP you do NOT need cross domain access, that was why jsonp was invented.. if I specify the datatype as json or jsonp it gives a response but triggers a parse error. When not using those datatypes it gives cross origin access denied error. You can just addapt my jsfiddle to play with it yourself. (Look in the resource console to see that the request loads correct with json) – Niki van Stein Dec 10 '15 at 17:04
  • Ah I should have take another minute. Yeah cross domain you are fairly limited. You could refer to the discussion here: https://stackoverflow.com/questions/7157455/how-to-do-cross-domain-ajax-in-jquery-with-datatype-text Or use JSON.stringify() on the return value. This will result in a bit of overhead. – Ajwhiteway Dec 10 '15 at 17:07
  • Stringify is no option due to the crash on parse, maybe a proxy server is the only way to go.. – Niki van Stein Dec 10 '15 at 17:21
  • That or { "text": } But if you have a parsing error due to encoding that won't help you. I couldn't tell you how much time I've lost to finding characters that weren't encoded in UTF8 while trying to parse JSON from unknown sources.... – Ajwhiteway Dec 10 '15 at 17:25
1

The server isn't returning JSONP, which is the root of the problem. You can't pass callback=? and just assume the server is going to wrap the response (it needs to be part of the architecture).

That said, you're running into two issues:

  1. The server doesn't implement CORS, so accessing the data as if it were on the same domain is forbidden (based on browser security policies).
  2. The server isn't wrapping the response in the supplied callback, so jQuery isn't picking up with its jQuery_* callback function.

I'm not familiar with the API, but if there isn't a specific way to get a JSONP response back (some are activated by the presence of a callback parameter, others by way of request URI, etc.), you're out of luck with retrieving data remotely using JavaScript (without running into the Cross-Domain policy).

--

To elaborate:

A server that supports JSONP, when used with jQuery, would return the response wrapped in the callback. e.g.

GET http://server.com/endpoint?callback=Foo

Results in something like:

Foo({json})

This service is still just returning {json} (well, specifically the following):

{"frames":[ ...snip... ],"frameInterval":60000}

Which makes JSONP a failed option.


Example using a proxy service found via a quick google (jsonp.afeld.me):

var proxyUrl = 'https://jsonp.afeld.me/';
var serviceUrl = "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001440043/timeline?gameHash=4725b07311676885";

$.ajax({
  url: proxyUrl + '?url=' + encodeURIComponent(serviceUrl) + '&callback=?',
  dataType: 'jsonp'
}).done(function(data){
  // `data` is a JSO, so serialize it before placing in the #output
  // element (otherwise we'll just see `[object Object]`)
  $('#output').text(JSON.stringify(data, null, '  '));
});
Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • Thank you for the suggestions and it is probably as you say. It is rather weird though that the browser does download the full response when loading with jsonp settings (not that it is usable in js..) – Niki van Stein Dec 10 '15 at 17:21
  • The browser will fetch the response, yes, but it won't know if it's correctly wrapped until it has [locally] screened/parsed it (before handing off to the page's script). – Brad Christie Dec 10 '15 at 17:22
  • @BasvanStein: Looks like, through a quick google search, there is a proxy you can use (jsonp.afeld.me). Here's an example of of your fiddle being (successfully) used with it: https://jsfiddle.net/6Lwjpjmo/25/ – Brad Christie Dec 10 '15 at 17:28