How to return a JSON object from an Azure Function with Node.js

20,622

Solution 1

Based on my recent testing (March 2017). You have to explicitly add content type to response headers to get json back otherwise data shows-up as XML in browser.

"Content-Type":"application/json"

res = {
    status: 200, /* Defaults to 200 */
    body: {message: "Hello " + (req.query.name || req.body.name)},
    headers: {
        'Content-Type': 'application/json'
    }
};

Full Sample below:

module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    context.log(context);

    if (req.query.name || (req.body && req.body.name)) {
        res = {
            // status: 200, /* Defaults to 200 */
            body: {message: "Hello " + (req.query.name || req.body.name)},
            headers: {
                'Content-Type': 'application/json'
            }
        };
    }
    else {
        res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
    }
    context.done(null, res);
};

Solution 2

If your data is a JS object, then this should just work, e.g.

module.exports = function(context, req) {
    context.res = {
        body: { name: "Azure Functions" }
    };
    context.done();
};

This will return an application/json response.

If instead you have your data in a json string, you can have:

module.exports = function(context, req) {
    context.res = {
        body: '{ "name": "Azure Functions" }'
    };

    context.done();
};

Which will return an application/json response because it sniffs that it is valid json.

Solution 3

module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');

if (req.query.name || (req.body && req.body.name)) {
    context.res = {
        // status: 200, /* Defaults to 200 */
        body: {"data":"Hello"},
        headers: {
            'Content-Type': 'application/json'
        }
    };
}
else {
    // res = {
    //     status: 400,
    //     body: "Please pass a name on the query string or in the request body"
    // };
}
context.done(null,res);

Solution 4

I would like to add one more point. Apart from making the body: a JSON object, the request should also contain proper headers telling server what content type we are interested in. I could see that same Azure function when just invoked via browser using URL gives XML response, but when invoking from script or tools like Postman it gives JSON.

Solution 5

I feel like the answer has been given but it hasn't been clearly presented so I thought I'd answer as well in case it will help anyone coming behind me. I too have created a function that most definitely returns a Javascript object but if I copy and paste the URL in the Azure Function UI and just open a new tab in Chrome and try to view the output, I actually get back an XML document that tells me there's an error (not surprising there's an error as many characters in the Javascript would have blown up the XML). So, as others have mentioned, the key is sending the appropriate headers with your request. When you copy/paste the URL into your browser, the browser is sending a request header that looks similar to this:

text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8

When that happens, you see the XML return as described in this link: https://github.com/strongloop/strong-remoting/issues/118

In order to get around this problem and see what the data would look like with a JSON request, either use a utility like Postman: https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en

Accept: application/json

Sample Postman Header Settings

Or use a CURL command and pass in the proper Accept header.

As you can see in the screenshot above, when I provided the proper header, I get back the JSON response I would expect.

Share:
20,622
Chris Dellinger
Author by

Chris Dellinger

Updated on July 14, 2022

Comments

  • Chris Dellinger
    Chris Dellinger almost 2 years

    With Azure Functions, what do you need to do to return a JSON object in the body from a function written in node.js? I can easily return a string, but when I try to return a json object as shown below I appear to have nothing returned.

    context.res = {
       body: jsonData,
       contentType: 'application/json'
    };
    
    • mathewc
      mathewc about 8 years
      Also note that to specify the content type of the response, you do that via the headers collection on the response, e.g. context.res.headers = { 'Content-Type': 'text/plain' }. As David says below, we'll default that to application/json for you if your response is json.
  • Matt Mazzola
    Matt Mazzola over 7 years
    Does this always work, meaning is the req and res always implicitly available and it will always make best guess about content types for output request objects? Or, is it only implied when your function is triggered by HTTP request? It was my understanding that only when function is triggered by http request does it implicitly add the request (input) and response (output) bindings. If it was any other tigger type I would need to manually add the response output binding and it also would not implicitly know to add content headers?
  • mathewc
    mathewc over 7 years
    Only for http requests is there any req/res. For other trigger types like queue, they are triggered internally - there is no request/response.
  • Lakshman Diwaakar
    Lakshman Diwaakar over 7 years
    I understood how azure functions return Json responses. I am having the authorisation level to be anonymous. when I invoke an http call, I receive a proper response in postman, but I could not receive when I use it in my react app. on digging deeper, I found out, I receive the response but the response's body is an object of readable stream. How do i get my response body? Any idea ? @david
  • David Ebbo
    David Ebbo over 7 years
    @LakshmanDiwaakar that sounds like a distinct question. Can you start a new one with more details about what you're doing? Or open issue on github.com/Azure/azure-webjobs-sdk-script
  • Lakshman Diwaakar
    Lakshman Diwaakar over 7 years
    @david I have posted as a separate question. Awaiting for your answer. stackoverflow.com/questions/39842944/…
  • rafaelbpa
    rafaelbpa almost 7 years
    where I should put this code? I'm trying to override my table.read(context). I have a json object that I got from my sql query (I joined two tables). But I don't know how to return this. =/
  • Brandon Wittwer
    Brandon Wittwer almost 7 years
    This helped me realize that chrome was sending accept headers that must not have jived with what the function was returning. Along with Allen Underwood's input, I now realize that I should pretty much just not use chrome to test the api. postman works great.
  • dance2die
    dance2die over 6 years
    @DavidEbbo I am tried this out on 11/25/2017 and headers needs to be specified to return JSON as @spooky answered in stackoverflow.com/a/42963573/4035
  • jikuja
    jikuja over 6 years
    What is performance of this compared to Azure's internal serialization?
  • Álvaro Agüero
    Álvaro Agüero about 4 years
    This works for me, you can add headers: { 'Content-Type': 'application/json' } for json response
  • toto'
    toto' almost 4 years
    this does not work for me. Does not return application/json, neither a message back.