0

I have a simple javascript/jquery code which requests a data from some web service which returns the data which can be used to create a highcharts bar chart. The response from the server can't be parsed into JSON as it contains a click event handler which fails to be parsed by JSON.parse with error Unexpected keyword ....

The javascript code looks like this

$.ajax({
    type:"POST",
    url:"service/call"
}).done(function( xdata ) {
  // this is not going to work as xdata is not object but plain text
  $('#container').highcharts(xdata);
});

The response from the server is like

{
 "chart" : {
   "type" : "bar"
 },
 "series" : [ {
   "data" : [ 25, 10 ]
 } ],
 "title" : {
   "text" : ""
 },
 "xAxis" : [ {
   "categories" : [ "data1", "data2"],
  "allowDecimals" : false
 } ],
 "yAxis" : [ {
   "title" : {
     "align" : "high",
     "text" : "Some Title"
   },
   "allowDecimals" : false,
   "labels" : {
     "overflow" : "justify"
   },
   "min" : 0
 } ],
 "credits" : {
   "enabled" : false
 },
 "plotOptions" : {
   "bar" : {
     "colors" : [ "#87bdee", "#ffcccc"],
     "colorByPoint" : true,
     "dataLabels" : {
       "enabled" : true
     },
  "point" : {
       "events" : {
         "click" : function(){window.location.href = '/data?type=' + (this.x == 0 ? 'data1' : (this.x == 1 ? 'hold' : (this.x == 2 ? 'data2' : (this.x == 3 ? 'data3' : (this.x == 4 ? 'data4' : (this.x == 5 ? 'data5' : (this.x == 6 ? 'data6' : 'data7')))))) )}
       }
     }
   }
 },
 "tooltip" : {
   "valueSuffix" : " elements"
 },
 "creditOptions" : {
   "enabled" : false
 }
}

I have access to both server and client side code.

So is there a easy way a making things work ? I mean how can I create the highchart without changing the response ?

7
  • 2
    It's trying to parse that response as JSON, but it's not JSON. You're not returning JSON. JSON is a specific format that only supports strings, numbers, objects, arrays, booleans and null. You cannot have a function inside of a JSON file/string. Commented Dec 5, 2016 at 20:03
  • You can try converting the function to a string, then parsing the function as string using eval() or Function Commented Dec 5, 2016 at 20:04
  • 1
    You can't have functions in JSON, it's purely a data format. You could have a string and run EVAL on it, or just have the function name and parameters (i.e keep the function defined on the client already, and just supply the parameters) Commented Dec 5, 2016 at 20:04
  • @RocketHazmat yep I know that, so I want to know is there a easy way somehow to create the chart using this response which I get from the server :) Commented Dec 5, 2016 at 20:04
  • Updated the question, just removed all the things about JSON, so I have a service which returns some data which needs to be used to create a highchart ... Commented Dec 5, 2016 at 20:17

2 Answers 2

2

You can indeed turn a function stored/passed as a string into callable code if you use JSON.stringify with a "replacer" function and JSON.parse with a "reviver" function along with new Function()

See this previous post of mine for a complete working example.

Sign up to request clarification or add additional context in comments.

7 Comments

I'm actually super conflicted about this answer. On one hand you have like 6 times the reputation that I do so I feel like you prolly know best, on the other this solution seems like cancer. So you dynamically create functions and give them their bodies? Again you have like 6 times my score, but are there any XSS problems with this? If not then i'm sad I didn't think of this.
Its an awful hack but its an awful hack that does what Babl requested. I can't think of a better way.
@bassxzero The ability to do what I'm showing is standard in the JSON object built into all modern browsers. I am not providing any commentary on "should you pass functions over HTTP and consume them in web clients". I am providing you with a perfectly legal and valid answer to your question. By the way, this solution is 10x better than eval() (as was suggested by others) because here, YOU control the reviver function, so you can scrub it for malicious content according to your own logic.
What I like in @ScottMarcus solution is that it needs no server side change.
@Babl Well, it actually does. The stringification takes place on the server and so the JSON.stringify(obj, replacer) would need to be on the server.
|
2

This is what I have done in the past.

<script type="text/javascript">

   function highChartOnClick() {
       alert('the click worked');
       window.location.href = '/data?type=' + (this.x == 0 ? 'data1' : (this.x == 1 ? 'hold' : (this.x == 2 ? 'data2' : (this.x == 3 ? 'data3' : (this.x == 4 ? 'data4' : (this.x == 5 ? 'data5' : (this.x == 6 ? 'data6' : 'data7')))))) );
   }

    $.ajax({
        type:"POST",
        url:"service/call"
    }).done(function( xdata ) {
         var someConfigurationJSONObject = xdata;
        someConfigurationJSONObject['plotOptions']['bar']['point']['events']['click'] = highChartOnClick;

         $('#container').highcharts(someConfigurationJSONObject);
    });
</script>

1 Comment

This solution is good when on client side you definitely know what the function should do, but in my case the function is something which is automatically generated at server side, so there is no way to have something like this. And I can't create a separate web service call just to get the functions .... But anyway thanks for help ....

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.