デシリアライズ時にのみ使用したいコンバーターがあります。そこで、CanWriteをfalseに設定しました。これは正常に機能し、すべてが正常にシリアル化されます。次に、Json文字列には、SantaClauseアイテムの配列とそれらが具象型SantaClauseであることを示す$typeを持つSantaClauseCollectionが含まれるオブジェクトグラフが含まれます。
ただし、逆シリアル化中にSantaClausのコレクションに遭遇すると、CanConvertを呼び出すことはありません(SantaClausCollectionを確認し、F5キーを押して続行します。その後、SantaClausのコレクション内のアイテムに遭遇すると、ブレークポイントに再び到達するはずです。しかし、そうではありません)。SantaClausアイテムに到達したときに、CanConvertを呼び出そうとはしていません。そのアイテムに対してCanConvertを呼び出して、コンバーターがそれを処理するかどうかを確認しなくても、代わりにそれ自体を逆シリアル化しようとします。これは、クラスにデフォルトコンストラクターがなく、プロパティ名が一致する規則を持つコンストラクターがないため、機能しません。
SantaClaus型に使用するコンストラクターが見つかりません。クラスには、デフォルトのコンストラクター、引数を持つ1つのコンストラクター、またはJsonConstructor属性でマークされたコンストラクターのいずれかが必要です。
このエラーが発生する理由は理解できますが、問題は、Json.netがCanConvertを呼び出して、コンバーターが逆シリアル化を処理するかどうかを確認するのではなく、オブジェクトを逆シリアル化しようとしたことを示しています。
コレクション内のアイテムごとにCanConvertが呼び出されないのはなぜですか?
私のコンバーター:
class SantaClaus2JsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(SantaClaus);
}
/// <summary>
/// Deserializes a SantaClaus as a SantaClausEx which has a matching constructor that allows it to deserialize naturally.
/// </summary>
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;//We only need this converter when reading.
}
}
}
SantaClausExは、SantaClausから継承して、プロパティに一致するように名前が変更されたパラメーターを持つコンストラクターを追加します。
class SantaClaus //a third party class I can't modify
{
string Name {get;set;}
public SantaClaus(string santaClauseName) { this.Name = santaClauseName }
}
class SantaClausEx:SantaClaus
{
//provide a constructor with param names matching property names
public SantaClausEx(string name) : base(name)
}
Json.netはSantaClausを逆シリアル化できませんが、SantaClauseExを逆シリアル化できます。
私はそのSantaClauseExクラスをどこでも使用していて、問題なく動作しますが、これを自動的に行うコンバーターを作成したかったのです。
これは、Jsonがコレクションに対してどのように見えるかです。
SantaClausCollection: [
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Bob"
},
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Jim"
}
]