56

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?

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Mehran
  • 15,593
  • 27
  • 122
  • 221

3 Answers3

84

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());
wal
  • 17,409
  • 8
  • 74
  • 109
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
17

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

Yishai Galatzer
  • 8,791
  • 2
  • 32
  • 41
  • Hmm, `JsonFormatter` doesn't exist anymore? – GregorMohorko Jan 17 '18 at 21:27
  • It does in WebAPI 2.x, what framework are you working in? Mvc Core? There you have an JsonInputFormatter and JsonOutputFormatter – Yishai Galatzer Jan 18 '18 at 19:21
  • .NET Framework 4.6.1. The only thing I found is `JsonConvert.DefaultSettings` which is of type `JsonSerializerSettings` and has a `ContractResolver` property, but then this approach is no different than the one from @Brian. – GregorMohorko Jan 18 '18 at 20:10
  • you are not saying what framework you are developing in. 4.6.1 is the .NET version, you might be doing MVC, WebAPI or WebForms. Both MVC and WebAPI come through NuGet packages, and my answer only refers to WebAPI – Yishai Galatzer Jan 19 '18 at 22:01
  • What exactly do you mean? I am developing a .NET library and using Newtonsoft.Json through NuGet. – GregorMohorko Jan 19 '18 at 22:04
  • If it is a standalone library, this is not relevant for you. If it is for a specific web framework – Yishai Galatzer Jan 19 '18 at 22:20
0

This approach from the question 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.

Florian Winter
  • 4,750
  • 1
  • 44
  • 69