Registering a custom JsonConverter globally in Json.Net

C#json.net

C# Problem Overview


Using Json.Net, I have properties in my objects which need special care in order to serialize / deserialize them. Making a descendant of JsonConverter, I managed to accomplish this successfully. This is the common way of doing this:

public class SomeConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        ...
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        ...
    }

    public override bool CanConvert(Type objectType)
    {
        ...
    }
}

class SomeClass
{
    [JsonProperty, JsonConverter(typeof(SomeConverter))]
    public SomeType SomeProperty;
}

//Later on, in code somewhere
SomeClass SomeObject = new SomeClass();
string json = JsonConvert.SerializeObject(SomeObject, new SomeConverter());

My problem with this code is that I need to introduce my custom converter in every serialization / deserialization. In my project there are many cases that I cannot do that. For instance, I'm using other external projects which make use of Json.Net as well and they will be working on my SomeClass instances. But since I don't want to or can't make change in their code, I have no way to introduce my converter.

Is there any way I can register my converter, using some static member perhaps, in Json.Net so no matter where serialization / deserialization happens, my converter is always present?

C# Solutions


Solution 1 - C#

Yes, this is possible using Json.Net 5.0.5 or later. See JsonConvert.DefaultSettings.

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new SomeConverter() }
};

// Later on...
string json = JsonConvert.SerializeObject(someObject);  // this will use SomeConverter

If you're using Web API, you can set up a converter globally like this instead:

var config = GlobalConfiguration.Configuration;
var jsonSettings = config.Formatters.JsonFormatter.SerializerSettings;
jsonSettings.Converters.Add(new SomeConverter());

Solution 2 - C#

Another approach (which wins in priority over the one @Brian mentions above) is to implement a custom contract resolver

JsonFormatter.SerializerSettings.ContractResolver = new CustomContractResolver();

And the implementation is rather straightforward

public class CustomContractResolver : DefaultContractResolver
{
    private static readonly JsonConverter _converter = new MyCustomConverter();
    private static Type _type = typeof (MyCustomType);

    protected override JsonConverter ResolveContractConverter(Type objectType)
    {
        if (objectType == null || !_type.IsAssignableFrom(objectType)) // alternatively _type == objectType
        {
            return base.ResolveContractConverter(objectType);
        }

        return _converter;
    }
}

Both methods are valid, this one is just a bigger hammer

Solution 3 - C#

This approach from the question https://stackoverflow.com/questions/17861700/asp-net-web-api-custom-jsonconverter-is-never-called works with Web API:

// Add a custom converter for Entities.
foreach (var formatter in GlobalConfiguration.Configuration.Formatters)
{
  var jsonFormatter = formatter as JsonMediaTypeFormatter;
  if (jsonFormatter == null)
    continue;

  jsonFormatter.SerializerSettings.Converters.Add(new MyConverter());
}

Just put it somewhere into Global.asax.

The other answers didn't work for me. DefaultSettings has no effect on Web API actions, and the JsonFormatter configuration property does not seem to exist in the .NET framework version I use.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMehranView Question on Stackoverflow
Solution 1 - C#Brian RogersView Answer on Stackoverflow
Solution 2 - C#Yishai GalatzerView Answer on Stackoverflow
Solution 3 - C#Florian WinterView Answer on Stackoverflow