Using System.Text.Json annotated objects in Newtonsoft.Json

Make System.Text.Json.Serialization attributes work no matter how your end-users want to deserialize your .NET objects.

Robert McLaws
CloudNimble
2 min readFeb 19, 2023

--

Over the weekend I ran into an issue where I was running unit tests and suddenly tests that worked before started failing. When I dug into it, the tests failed because the objects weren’t deserializing from JSON properly.

Turns out I had upgraded some code to split support for both System.Text.Json AND Newtonsoft.Json, and in the process I changed the object model to use the System.Text.Json attributes. Obviously, those attributes don’t work in Newtonsoft.Json, so the objects weren’t going to materialize properly.

So I dug into Newtonsoft.Json’s extensibility, and found the IContractResolver interface. So I decided to build a SystemTextJsonContractResolver to make attributes like [JsonPropertyName] and [JsonIgnore] usable.

The result is in the EasyAF.NewtonsoftJson.Compatibility package on NuGet.

All it takes is to leverage the JsonSerialiazerSettings to add the resolver, like this:

var content = "{/"SomeValue/":5}";
var settings = new JsonSerializerSettings()
{
ContractResolver = new SystemTextJsonContractResolver(),
};
var result = JsonConvert.DeserializeObject<SomeObject>(content, settings);

The resolver will run the default property conversion first, and then if it finds [JsonIgnore], [JsonExtensionData], or [JsonPropertyName], it will override the default settings with the information from those attributes.

I validated the concept against another resolver I found in the NJsonSchema library. The implementations are similar, but the EasyAF version is more lightweight.

So please, try it out and let me know if it helps your projects!

--

--

Robert McLaws
CloudNimble

Founder & CEO of BurnRate (@BurnRate_io). Serial entrepreneur. Former Microsoft MVP. @dotnetfdn member. Helping founders build amazing businesses.