Menu
Cutty
  • Chryslers
  • Lutherie
  • YLSNED
  • About
Cutty

Serializing List<Dictionary<string, object>> not working in dotnet core 8.0

Posted on August 22, 2024August 22, 2024 by Iain 'Cutty' Carlin

My previously working code (dotnet 6.0) that was serialising a complex object, stopped producing Json output at the API controller. The object(s) are defined as:

    public class ReportResultsDTO
    {
        public string ReportTitle { get; set; }
        public List<ReportResultDTO> Results { get; set; } = [];
    }

    public class ReportResultDTO
    {
        public string Title { get; set; }
        public List<Dictionary<string, object>> Data;
    }

Turns out that because System.Net.Text is now used by default (rather than Newtonsoft.Json) it doesn’t handle converting List<Dictionary<string, object>> to Json. I tried converting it to a Json string first and outputting that, but the returned string was full of \” characters to escape the string(s).

I’m trying to remove the dependency on Newtonsoft throught the code so didn’t really want to have to make the controllers use it just for the sake of one controller. Luckily I found: https://stackoverflow.com/questions/78123885/asp-net-core-3-1-use-newtonsoft-json-only-in-some-controllers

I created a custom ActionFilterAttribute to handle converting the result for the specific controller:

public class ReportResultsJsonFormatterAttribute : ActionFilterAttribute
{
    /// <summary>
    /// Attribute to override output action to Newtonsoft
    /// </summary>
    /// <param name="context"></param>
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        if (context.Result is ObjectResult objectResult)
        {
            IOptions<MvcNewtonsoftJsonOptions> jsonOptions = context.HttpContext.RequestServices.GetService<IOptions<MvcNewtonsoftJsonOptions>>();

            objectResult.Formatters.RemoveType<SystemTextJsonOutputFormatter>();
#pragma warning disable CS0618 // Type or member is obsolete
            objectResult.Formatters.Add(new NewtonsoftJsonOutputFormatter(
                jsonOptions.Value.SerializerSettings,
                context.HttpContext.RequestServices.GetRequiredService<ArrayPool<char>>(),
                context.HttpContext.RequestServices.GetRequiredService<IOptions<MvcOptions>>().Value));
#pragma warning restore CS0618 // Type or member is obsolete
        }
        else
        {
            base.OnActionExecuted(context);
        }
    }
}

Which is applied to the controller thus:

        [ReportResultsJsonFormatter]
        [Produces("application/json")]
        [HttpPost("{reportId:int}/execute")]
        public async Task<IActionResult> ExecuteReportAsync(int reportId, ReportParameters reportParameters = null, string reportAccessCode = null)

and everything was back to the way it worked previously.

Recent Posts

  • 2024 was the best year for our solar system
  • Books I read in 2024
  • Books I read in 2023
  • Happy New Year 2024
  • Lawson – A life in words and music

Categories

  • Chryslers (1)
  • Cutty's Blog (12)
  • Lutherie (38)
  • You Learn Something New Every Day (43)
©2025 Cutty | Powered by Superb Themes