61

I am playing with Azure Functions. However, I feel like I'm stumped on something pretty simple. I'm trying to figure out how to return some basic JSON. I'm not sure how to create some JSON and get it back to my request.

Once upon a time, I would create an object, populate its properties, and serialize it. So, I started down this path:

#r "Newtonsoft.Json"

using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"Running Function");    
    try {      
      log.Info($"Function ran");

      var myJSON = GetJson();

      // I want myJSON to look like:
      // {
      //   firstName:'John',
      //   lastName: 'Doe',
      //   orders: [
      //     { id:1, description:'...' },
      //     ...
      //   ]
      // }
      return ?;
    } catch (Exception ex) {
        // TODO: Return/log exception
        return null;
    }
}

public static ? GetJson() 
{
  var person = new Person();
  person.FirstName = "John";
  person.LastName = "Doe";

  person.Orders = new List<Order>();
  person.Orders.Add(new Order() { Id=1, Description="..." });

  ?
}

public class Person 
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public List<Order> Orders { get; set; }
}

public class Order
{
  public int Id { get; set; }
  public string Description { get; set; }
}

However, I'm totally stuck on the serialization and return process now.I guess I'm used to returning JSON in ASP.NET MVC where everything is an Action

OmG
  • 18,337
  • 10
  • 57
  • 90
xam developer
  • 1,923
  • 5
  • 27
  • 39
  • You have some answers - please mark one as the answer to your question. I provided an up-to-date answer based on the recent documentation. – hansmbakker Aug 31 '17 at 10:25

10 Answers10

50

Here's a full example of an Azure function returning a properly formatted JSON object instead of XML:

#r "Newtonsoft.Json"
using System.Net;
using Newtonsoft.Json;
using System.Text;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    var myObj = new {name = "thomas", location = "Denver"};
    var jsonToReturn = JsonConvert.SerializeObject(myObj);

    return new HttpResponseMessage(HttpStatusCode.OK) {
        Content = new StringContent(jsonToReturn, Encoding.UTF8, "application/json")
    };
}

Navigate to the endpoint in a browser and you will see:

{
  "name": "thomas",
  "location": "Denver"
}
Levi Fuller
  • 13,631
  • 4
  • 38
  • 44
37

The easiest way is perhaps to

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "/jsontestapi")] HttpRequest req,
    ILogger log)
{
    return new JsonResult(resultObject);
}

Will set the content-type to application/json and return the json in the response body.

Bjorn Reppen
  • 22,007
  • 9
  • 64
  • 88
  • 1
    I used this and passed some settings to `JsonResult` (eg: `new JsonSerializerSettings()`) but then it throws error saying that `'JsonResult.SerializerSettings' must be an instance of type 'Newtonsoft.Json.JsonSerializerSettings'`.. Which it is... any idea how to pass those settings? – Marian Simonca Jan 31 '20 at 12:07
  • Simple and quick to implement. Thank you! <3 – ReGaSLZR Mar 28 '22 at 16:20
  • JsonResult - internally uses NewtonSoft.JSON which is slower than System.Text.Json. So if performance is the key, this might not be a good idea. – Hasnu zama Mar 02 '23 at 19:26
23

You can take req from

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)

and create the response using

return req.CreateResponse(HttpStatusCode.OK, json, "application/json");

or any of the other overloads in assembly System.Web.Http.

More info on learn.microsoft.com

hansmbakker
  • 1,108
  • 14
  • 29
  • 6
    I prefer to use: `req.CreateResponse(HttpStatusCode.OK, json, JsonMediaTypeFormatter.DefaultMediaType);`. I think it is safer than a `application/json` string. – DoronG Sep 08 '17 at 20:30
  • nice one, is there any way to convert it into XML? – Farzad J Mar 14 '18 at 10:21
  • This didnt solve my issue. I assume that it is because the json was not generated in my function but comes from http call. The answer from Levi Fuller did fix my issue. – Noldy Apr 08 '19 at 11:11
7

It looks like this can be achieved just by using the "application/json" media type, without the need to explicitly serialize Person with Newtonsoft.Json.

Here is the full working sample that results in Chrome as:

{"FirstName":"John","LastName":"Doe","Orders":[{"Id":1,"Description":"..."}]}

The code is given as below:

[FunctionName("StackOverflowReturnJson")]
    public static HttpResponseMessage Run([HttpTrigger("get", "post", Route = "StackOverflowReturnJson")]HttpRequestMessage req, TraceWriter log)
    {
        log.Info($"Running Function");
        try
        {
            log.Info($"Function ran");

            var myJSON = GetJson();  // Note: this actually returns an instance of 'Person' 

            // I want myJSON to look like:
            // {
            //   firstName:'John',
            //   lastName: 'Doe',
            //   orders: [
            //     { id:1, description:'...' },
            //     ...
            //   ]
            // }
            var response = req.CreateResponse(HttpStatusCode.OK, myJSON, JsonMediaTypeFormatter.DefaultMediaType); // DefaultMediaType = "application/json" does the 'trick'
            return response;
        }
        catch (Exception ex)
        {
            // TODO: Return/log exception
            return null;
        }
    }

    public static Person GetJson()
    {
        var person = new Person();
        person.FirstName = "John";
        person.LastName = "Doe";

        person.Orders = new List<Order>();
        person.Orders.Add(new Order() { Id = 1, Description = "..." });

        return person;
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public List<Order> Orders { get; set; }
    }

    public class Order
    {
        public int Id { get; set; }
        public string Description { get; set; }
    }
Hafiz Mujadid
  • 1,565
  • 1
  • 15
  • 27
Dima G
  • 1,945
  • 18
  • 22
  • nice one, is there any way to convert it into XML? – Farzad J Mar 14 '18 at 10:21
  • XML is the default.. just drop the `JsonMediaTypeFormatter.DefaultMediaType` parameter, so you'll have: `var response = req.CreateResponse(HttpStatusCode.OK, myJSON);` – Dima G Mar 15 '18 at 12:56
  • 1
    This is the best answer in my opinion because formatter already uses Newtonsoft. You should have called the function GetPerson() rather than GetJson(). The function isn't returning Json but an object and it is confusing at the first glance. – Jovica Zaric Apr 26 '18 at 09:03
5

JSON is pretty easy, Newtonsoft.Json library is a special case. You can include it by adding this at the top of the script file:

#r "Newtonsoft.Json"

using Newtonsoft.Json;

Then your function becomes:

public static string GetJson() 
{
  var person = new Person();
  person.FirstName = "John";
  person.LastName = "Doe";

  person.Orders = new List<Order>();
  person.Orders.Add(new Order() { Id=1, Description="..." });

  return JsonConvert.SerializeObject(person);
}
juunas
  • 54,244
  • 13
  • 113
  • 149
  • 1
    But how do I return that from the `Run` method? The `Run` method returns a `HttpResponseMessage` which is not a string. Yet, I don't want to return a raw string. Rather I want to return JSON. – xam developer Aug 14 '16 at 21:46
  • One way is just to create an HttpResponseMessage manually. Set it's content as StringContent with the Json. – juunas Aug 14 '16 at 22:15
  • You can see an example here: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/action-results – juunas Aug 14 '16 at 22:19
  • nice one, is there any way to convert it into XML? – Farzad J Mar 14 '18 at 10:20
  • I think that should be a separate question (unless one exists already). Most people are not going to find an answer posted in comments. – juunas Mar 14 '18 at 10:32
2

You can change the method signature into:

public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)

and it will allow JSON data to be returned.

Burak Tasci
  • 887
  • 12
  • 18
  • 3
    Just tried on Azure portal, and that helped me to return JSON too: `return req.CreateResponse(HttpStatusCode.OK, result, "application/json");`, without playing with the method signature – Burak Tasci Mar 16 '17 at 14:43
2

I had a similar issue and this seemed to be the most popular post with no answer. After figuring what node does the below should work and give you exactly what you are after. The other examples still returns a string representation wheres this will return JSON.

Remember to declare using System.Text; and also add:

return JsonConvert.SerializeObject(person);

to the GetJson function as per Juunas response.

    return new HttpResponseMessage(HttpStatusCode.OK)
       {
           Content = new StringContent(GetJson(), Encoding.UTF8, "application/json")
       };
Martin Evans
  • 45,791
  • 17
  • 81
  • 97
Matt
  • 31
  • 3
0
#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static IActionResult Run(HttpRequest req, ILogger log)
{    
    (string name, string surname) = ("James", "Ozzy");
    return new ObjectResult(new { name, surname }) ;
 }
Melih
  • 323
  • 3
  • 11
0

You can to create the owner response:

 var response = new HttpResponseMessage(HttpStatusCode.OK) { 
                Content = json
            };
 return new ObjectResult(response);
0

If you are using neither Newtonsoft.Json or System.Web.Http (as in this answer)

var msg = new Msg("Hello, World");

var response = req.CreateResponse(HttpStatusCode.OK);
response.WriteAsJsonAsync(msg);
return response;
Zak
  • 936
  • 10
  • 19