0

We have

  1. C# WebAPI server backend
  2. node JS client SPA frontend

One of our APIs generates a C# object which represents a ChartJS model. Like so

public virtual IActionResult Chart()
{
        var chartModel = GetChart();
        return new ObjectResult(chartModel);
}

The ChartModel class simplified looks like this

public class ChartJSModel
{
    ...
    public string callback { get; set; } //FUNCTION
    ...
}

The client receives this JSON ObjectResult (again simplified)

{
    "callback": "function(value, index, values) { return Number(value.toString());}"        
}

The callback function is in quotes. This breaks ChartJS.

Question

  1. So JSON is purely meant for data description language but how do I get the C# WebAPI to send back the callback without quotes?
  2. I could process the JSON on the client but maybe there is an alternative.
6
  • you can't have functions in JSON - in JSON, values can only be ... object, array, string, number, null, true or false Commented Sep 19, 2019 at 12:20
  • 1
    Whenever response happen, model will convert to json so better to handle it UI side or as alternate use xml as media formatter instead json and then convert xml to json at ui side. I know its not optimal solution but just to fulfill your purpose. Commented Sep 19, 2019 at 12:31
  • 1
    that's not to say what you want to do is unachievable - you'll just have to think outside the box ... e.g. on the server send { "callback": "fn1" } ... in the client, process the parsed JSON (i,e, the javascript Object you now have) and look for callback key, and changing the value accordingly ... "fn1" to function(.... etc Commented Sep 19, 2019 at 12:33
  • @HarshadVekariya - how will XML, also a text only response, help Commented Sep 19, 2019 at 12:33
  • Check answer to return xml: stackoverflow.com/questions/18266952/… . Though its for json but you can change code accordingly. Commented Sep 19, 2019 at 12:38

1 Answer 1

1

you can't have functions in JSON - in JSON, values can only be ... object, array, string, number, null, true or false

that's not to say what you want to do is unachievable - you'll just have to think outside the box ... e.g. on the server send { "callback": "fn1" } ... in the client, process the parsed JSON (i,e, the javascript Object you now have) and look for callback key, and changing the value accordingly ... "fn1" to function(.... etc

so, if you change your server code to send something like

{
    "type": "line",
    "data": {
        "datasets": [
        ]
    },
    "options": {
        "scales": {
            "xAxes": [{
                    "type": "logarithmic",
                    "position": "bottom",
                    "ticks": {
                        "beginAtZero": false,
                        "min": 0.0,
                        "max": "NaN",
                        "stepSize": "NaN",
                        "callback": "fn1"
                    },
                }
            ],
            "yAxes": [{
                    "type": "logarithmic",
                    "position": "left",
                    "ticks": {
                        "beginAtZero": false,
                        "min": 0.0,
                        "max": "NaN",
                        "stepSize": "NaN",
                        "callback": "fn1arrow"
                    },
                }
            ]
        },

    }
}

Then you can write a function like

function fixCallbacks(obj) {
    const fns = {
        fn1: function(value, index, values) { return Number(value.toString());},
        fn1arrow: (value, index, values) => Number(value.toString()),
    };
    Object.entries(obj).forEach(([k, v]) => {
        if (typeof v === 'object' || typeof v === 'array') {
            fixCallbacks(v);
        } else if (k === 'callback') {
            obj[k] = fns[v] || obj[k];
        }
    });
}

Note: fn1 and fn1arrow do the same thing, just showing you can use functions and arrow functions as a solution

And it should work - like this

const data = {
    "type": "line",
    "data": {
        "datasets": [
        ]
    },
    "options": {
        "scales": {
            "xAxes": [{
                    "type": "logarithmic",
                    "position": "bottom",
                    "ticks": {
                        "beginAtZero": false,
                        "min": 0.0,
                        "max": "NaN",
                        "stepSize": "NaN",
                        "callback": "fn1"
                    },
                }
            ],
            "yAxes": [{
                    "type": "logarithmic",
                    "position": "left",
                    "ticks": {
                        "beginAtZero": false,
                        "min": 0.0,
                        "max": "NaN",
                        "stepSize": "NaN",
                        "callback": "fn1arrow"
                    },
                }
            ]
        },

    }
};

function fixCallbacks(obj) {
    const fns = {
        fn1: function(value, index, values) { return Number(value.toString());},
        fn1arrow: (value, index, values) => Number(value.toString()),
    };
    Object.entries(obj).forEach(([k, v]) => {
        if (typeof v === 'object' || typeof v === 'array') {
            fixCallbacks(v);
        } else if (k === 'callback') {
            obj[k] = fns[v] || obj[k];
        }
    });
}

// here we "fix" the data
fixCallbacks(data);
//
console.log(data);

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

3 Comments

Thanks for that Javascript in the middle.
@robor78 - not sure what you mean by "that Javascript in the middle" - it's the code you would need, the snippet is to demonstrate it works :
I'm refering to fixCallbacks. My javascript is a little rusty, so I was already wondering how to find all the "callbacks" in the JSON object. Your function fixCallbacks does that. Thanks.

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.