How can I tell which JSON serialization will be used on my Azure function?

76 views Asked by At

In Visual Studio, if I create a new project using the "Azure Functions" template, the JSON serialization used by that function will be different depending on which version of the template I use. I'm wondering how can I tell which JSON serialization will be used, solely from looking at the code/project.

Minimal complete and viable example

(you need to have the Visual Studio "Azure" workload installed to do this)

  1. Create a new project using the "Azure Functions" template, choose ".NET 6.0 (Long term support)" and use the default options for everything else.
  2. Replace the string responseMessage and return lines with this code:
            var content = new ResponseContent();
            return new OkObjectResult(content);
  1. Add this class to the project:
    public class ResponseContent
    {
        [Newtonsoft.Json.JsonProperty("CouldBeThis")]
        public string Example { get; set; } = "MyValue";
    }
  1. Create a new project using the "Azure Functions" template, choose ".NET 6.0 Isolated (Long Term Support)" and use the default options for everything else.
  2. Replace the return line with the same code as shown in 2.
  3. Add this class to the project:
    public class ResponseContent
    {
        [System.Text.Json.Serialization.JsonPropertyName("ButMaybeThis")]
        public string Example { get; set; } = "MyValue";
    }
  1. Run both projects, and use a browser to visit the URL shown for each project. The outputs are, respectively:
{
    "CouldBeThis": "MyValue"
}

and

{
    "ButMaybeThis": "MyValue"
}

The above is demonstrating that one project is using Newtonsoft.Json for Json serialization, but the other is using System.Text.Json. But if I had not yet put any attributes on that object, then how could I have determined which JSON serialization will be used, solely from looking at the code/project?

EDIT after request to add the complete function code

Here's the complete in-process function (steps 1-3 above):

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace FunctionAppA
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            ResponseContent content = new ResponseContent();
            return new OkObjectResult(content);
        }
    }

    public class ResponseContent
    {
        [Newtonsoft.Json.JsonProperty("CouldBeThis")]
        public string Example { get; set; } = "MyValue";
    }
}

and here's the complete isolated version

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace FunctionAppI
{
    public class Function1
    {
        private readonly ILogger<Function1> _logger;

        public Function1(ILogger<Function1> logger)
        {
            _logger = logger;
        }

        [Function("Function1")]
        public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
        {
            _logger.LogInformation("C# HTTP trigger function processed a request.");
            ResponseContent content = new ResponseContent();
            return new OkObjectResult(content);
        }

        public class ResponseContent
        {
            [System.Text.Json.Serialization.JsonPropertyName("ButMaybeThis")]
            public string Example { get; set; } = "MyValue";
        }
    }
}
1

There are 1 answers

3
Pravallika KV On

AFAIK in the latest versions, Azure Functions by default uses the venerable Newtonsoft.Json package. This package is included as a dependency of the Microsoft.NET.Sdk.Functions package in .csproj project file.

Though Azure Functions uses the same OkObjectResult class from ASP.NET Core framework, the serialization process in Azure Functions is handled differently due to its reliability on Newtonsoft.Json.

  1. If the function code has using Newtonsoft.Json namespace and Microsoft.NET.Sdk.Functions , Microsoft.AspNetCore.Mvc packages in your project, it indicates the use of Newtonsoft.Json:
<ItemGroup>
  <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
</ItemGroup>

enter image description here

  • The code uses methods like JsonConvert.SerializeObject() or JsonConvert.DeserializeObject().
  1. If your function code has using System.Text.Json namespace, and Microsoft.Azure.Functions.Extensions , Microsoft.AspNetCore.Mvc.Json packages in your csproj file, it indicates the use of System.Text.Json.
<ItemGroup>
  <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
</ItemGroup>
  • The code uses methods like JsonSerializer.Serialize() or JsonSerializer.Deserialize().

Note: The function code you have provided is using Newtonsoft.json.

References:

https://svrooij.io/2023/07/26/system-text-json-azure-functions/