Search code examples
javascriptnode.jsjsonaxiosobject-literal

How to send javascript object literals from a Node backend to the browser frontend?


I am using Node where I have JavaScript object literals with methods in the backend, e.g.:

const report = {
    id: 1,
    title: 'Quarterly Report for Department 12345',
    abstract: 'This report shows the results of the sales and marketing divisions.', 
    searchText: function () {
        return this.title + '|' + this.abstract;
    }
};

And I want to send these object literals to the frontend via AJAX and be able to call the methods on these objects as I can in the backend.

But even though I can send the objects to the frontend without JSON.stringify(), they are still converted to plain JSON by the time they reach my frontend:

enter image description here

Am I missing something, or is there not a way to send full object literals from backend to frontend. I'm using Axios.


Solution

  • But even though I can send the objects to the frontend without JSON.stringify(),

    It sounds like you are using JSON.stringify … just indirectly (via a library).

    JSON has no function data type. So you can't just use JSON.

    You have a few options.

    Listed in the order I'd recommend them in.


    Resolve the methods

    In your example, your function simple return this.title + '|' + this.abstract; so you could replace it with a string:

    const report = {
        id: 1,
        title: 'Quarterly Report for Department 12345',
        abstract: 'This report shows the results of the sales and marketing divisions.', 
        searchText: 'Quarterly Report for Department 12345|This report shows the results of the sales and marketing divisions.'
        }
    };
    

    You could use the replacer argument of JSON.stringify to do this automatically for any method on the object.

    This is the simplest option but results in data that doesn't update dynamically so it might not be suitable for your needs.

    Add the methods with client-side code

    Send a simple object which doesn't have the method but does have a field which describes the type of object it does.

    Then inflate it on the client:

    const type = ajaxResponse.type;
    const Constructor = collectionOfConstructorFunctions[type];
    const data = new Constructor(ajaxResponse.data);
    

    Send JavaScript instead

    You could use JSONP instead of Axios.

    The response would be application/javascript instead of application/json so you could encode function expressions in the returned data.

    I don't recommend this option.

    Encode the functions in the JSON and then include them client-side

    This is horrible.

    const report = {
        id: 1,
        title: 'Quarterly Report for Department 12345',
        abstract: 'This report shows the results of the sales and marketing divisions.',
        searchText: "return this.title + '|' + this.abstract;"
    }
    

    and then, on the client:

    report.searchText = new Function(report.searchText);
    console.log(report.searchText());
    

    This is effectively using eval. Don't do it.