I want to modify my json.NET serializer to add the $type property only to the objects which implements a given interface but not to any property or nested objects.
With TypeNameHandling.Auto (default)
{
"PropertyA": 123,
"PropertyB": "foo",
"PropertyC": [1, 2, 3, 4]
}
With TypeNameHandling.All
{
"$type": "JsonNetTypeNameHandling.TestEvent, jsonNetTypeNameHandling",
"PropertyA": 123,
"PropertyB": "foo",
"PropertyC": {
"$type": "System.Collections.Generic.List`1[[System.Int32, mscorlib]], mscorlib",
"$values": [1, 2, 3, 4 ]
}
}
What I want
{
"$type": "JsonNetTypeNameHandling.TestEvent, jsonNetTypeNameHandling",
"PropertyA": 123,
"PropertyB": "foo",
"PropertyC": [1, 2, 3, 4]
}
I am experimenting with a custom ContractResolver but I don't get it to work:
class Program
{
static void Main(string[] args)
{
var serializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple,
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
ContractResolver = new EnableTypeNameHandlingAllOnlyForEvents(),
Formatting = Formatting.Indented
};
var event1 = new TestEvent() { PropertyA = 123, PropertyB = "foo", PropertyC = new List<int> { 1, 2, 3, 4 } };
string event1Serialized = JsonConvert.SerializeObject(event1, serializerSettings);
Console.WriteLine(event1Serialized);
Console.ReadLine();
}
}
public interface IEvent
{
}
public class TestEvent : IEvent
{
public int PropertyA { get; set; }
public string PropertyB { get; set; }
public List<int> PropertyC { get; set; }
}
public class EnableTypeNameHandlingAllOnlyForEvents : DefaultContractResolver
{
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var x = base.CreateObjectContract(objectType);
if (typeof(IEvent).IsAssignableFrom(x.UnderlyingType))
{
// What to do to tell json.NET to add $type to instances of this (IEvent) type???
}
return x;
}
}
See Question&Answers more detail:
os