Dictionary serialization: System.Exception: Type <Type> is not a dictionary

I have a dictionary in my type, which I want to get as input on controller:

using Newtonsoft.Json;

namespace LM.WebApp.Models.ApiModels;

[JsonDictionary]
public class Values
{
    public Dictionary<string, string> values { get; set; }
}

public class Data
{
    public bool is_active { get; set; }
    public IList<string> labels { get; set; }
    public string name { get; set; }
    public Values values { get; set; }
}

public class DictionaryImportApiModel
{
    public IList<Data> data { get; set; }
}

I’m passing on input this test JSON:

{
  "data":
  [
    {
      "is_active": true,
      "labels": [
        "SYSTEM",
        "EXTERNAL"
      ],
      "name": "MEDICATION_REQUEST_INTENT",
      "values": {
        "order": "Замовлення ліків",
        "plan": "План застосування"
      }
    }
  ]
}

And getting error from question title and null dictionary in inbound object. I have changed Newtonsoft.Json serializer to Microsoft.AspNetCore.Mvc.NewtonsoftJson and removed attribute [JsonDictionary] from Values class and added .AddNewtonsoftJson() just after AddControllersWithViews in Startup. Exception is gone, but dictionary in inbound object is still null. Is it necessary to use custom converters (like this)
to handle dictionary?

>Solution :

Change values type of Data model to Dictionary<string, string>:

public class Data
{
    public bool is_active { get; set; }
    public IList<string> labels { get; set; }
    public string name { get; set; }
    public Dictionary<string, string> values { get; set; }
}

One of the conventions supported by main .NET json serializers (both Newtonsoft.Json and System.Text.Json, maybe some others, but have not worked with them) is converting json object to and from Dictionary, so you don’t need extra wrapper class Values.

P.S.

Unless you have specific naming conventions in your project – there is no need to name classes properties the same way as they are named in the source json. For Newtonsoft.Json you can either mark properties with JsonPropertyAttribute or trying to setup corresponding NamingStrategy in serializer settings (System.Text.Json has similar options).

Leave a Reply