Possiedo un convertitore che desidero utilizzare solo durante la deserializzazione. Così ho impostato CanWrite su false, che funziona bene e tutto si serializza bene. La stringa Json contiene quindi un grafico oggetto all'interno del quale è presente una SantaClauseCollection con una matrice di elementi SantaClause e un tipo $ che indica che sono di tipo concreto SantaClause.JSON.Net non sta chiamando CanConvert per l'articolo da collezione?
Tuttavia, quando incontra una raccolta di SantaClaus durante la deserializzazione, non chiama mai CanConvert (ho un punto di interruzione e vedo SantaClausCollection, premete F5 per continuare, che dovrebbe quindi colpire nuovamente il punto di interruzione quando si incontra un oggetto nel collezione di SantaClaus, ma non è così). Non sta cercando di chiamare CanConvert quando arriva all'elemento SantaClaus. Senza nemmeno chiamare CanConvert per quell'elemento per verificare se il mio convertitore lo gestirà, cercherà invece di deserializzare esso stesso, che non funzionerà perché la classe non ha costruttori predefiniti e nessun costruttore con convenzioni di corrispondenza nome-proprietà:
Impossibile trovare un costruttore da utilizzare per il tipo SantaClaus. Una classe deve avere un costruttore predefinito, un costruttore con argomenti o un costruttore contrassegnato con l'attributo JsonConstructor.
capisco perché ottengo questo errore, ma il problema è che indica che Json.net cercato di deserializzare l'oggetto, invece di chiamare CanConvert per controllare e vedere se il mio convertitore voleva gestire la deserializzazione, invece.
Perché non è possibile chiamare CanConvert per ogni articolo della raccolta?
mio convertitore:
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 è solo eredita da SantaClaus per aggiungere un costruttore con un parametro rinominato per abbinare proprietà:
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 non può deserializzare un SantaClaus, ma può deserializzare un SantaClauseEx.
Io uso quella classe SantaClauseEx ovunque e funziona perfettamente, ma volevo fare un convertitore per farlo automaticamente.
Questo è ciò che il JSON sembra per la raccolta:
SantaClausCollection: [
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Bob"
},
{
$type: "SantaClaus, XMasClasses.NET20"
Name: "St. Jim"
}
]
Come stai effettivamente effettuando la chiamata di conversione? I metodi Serialize/Deserialize di solito contengono sovraccarichi che accettano convertitori da utilizzare se applicabile. Il tuo convertitore non verrà chiamato magicamente solo perché esiste, ma deve essere passato come uno di quei convertitori. –