I have a converter that I want to use only for deserialization. So I set CanWrite to false, which works fine and everything Serializes fine. The Json line then contains a graph of objects within which there is a SantaClauseCollection with an array of SantaClause elements and a type $ indicating that they are a specific type of SantaClause.
However, when it encounters the SantaClaus collection during deserialization, it never calls CanConvert (I have a breakpoint and see SantaClausCollection, press F5 to continue, after which it hits the breakpoint again when it encounters an item in the collection from Santa -Klaus, but it’s not). It does not try to call CanConvert when it hits the SantaClaus element. Without even calling CanConvert for this element to check whether my converter will handle it, he instead tries to deserialize it himself, which will not work, because the class does not have a default constructor and does not have a constructor with property matching conventions:
Unable to find constructor for type SantaClaus. The class must have a default constructor, one constructor with arguments, or a constructor marked with the JsonConstructor attribute.
I understand why I get this error, but the problem is that it indicates that Json.net tried to deserialize the object, instead of calling CanConvert to check if my converter wants to handle deserialization.
Why is CanConvert not called for every item in the collection?
My converter:
class SantaClaus2JsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(SantaClaus);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize<SantaClausEx>(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanWrite
{
get
{
return false;
}
}
}
SantaClausEx simply inherits from SantaClaus to add a constructor with a renamed parameter to match the properties:
class SantaClaus
{
string Name {get;set;}
public SantaClaus(string santaClauseName) { this.Name = santaClauseName }
}
class SantaClausEx:SantaClaus
{
public SantaClausEx(string name) : base(name)
}
Json.net cannot deserialize SantaClaus, but it can deserialize SantaClauseEx.
I use this SantaClauseEx class everywhere and it works fine, but I wanted to make this converter automatically.
Json :
SantaClausCollection: [
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Bob"
},
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Jim"
}
]