我有一个抽象类KVP的队列。我对从KVP继承的2个不同对象进行排队。当我序列化队列时,一切都很好,但由于不能构造KVP,它在反序列化时失败了。
如果它是一个非通用对象,我可以将其反序列化为动态对象,但我不确定如何反序列化既可以包含事件又可以包含ID的队列。
样本代码:
public virtual async Task<bool> LoadFromFile(string FileName, bool addToExistingQueue,bool DeleteFileAfterLoad = true)
{
try
{
IFile File = await PCLStorage.FileSystem.Current.LocalStorage.GetFileAsync(FileName);
var serializedText = await File.ReadAllTextAsync();
var mQueue = JsonConvert.DeserializeObject<Queue<T>>(serializedText,jss);
if (!addToExistingQueue)
{
_queue = new ConcurrentQueue<T>();
}
while (mQueue.Count > 0)
{
_queue.Enqueue(mQueue.Dequeue());
}
if (DeleteFileAfterLoad)
{
await File.DeleteAsync();
}
return true;
}
catch (Exception ex)
{
Debug.WriteLine("Could not load File. Exception Message: " + ex.Message);
return false;
}
}
public virtual async Task<bool> WriteToFile(string FileName)
{
try
{
Debug.WriteLine("Writing File: " + FileName);
var File = await FileSystem.Current.LocalStorage.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);
var serializedText = JsonConvert.SerializeObject(_queue.ToList(),jss);
await File.WriteAllTextAsync(serializedText);
return true;
}
catch (Exception ex)
{
Debug.WriteLine("Could not write File with exception message: " + ex.Message);
return false;
}
}
您可以
-
启用TypeNameHandling(在序列化和反序列化中):
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; var serializedText= JsonConvert.SerializeObject(mQueue, settings);
然后是
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; var mQueue = JsonConvert.DeserializeObject<Queue<T>>(serializedText, settings);
这为多态类添加了一个额外的
"$type"
属性,如本文所述。在选择此解决方案之前,有关使用
TypeNameHandling
可能存在的安全问题的讨论,请参阅Newtonsoft Json中的TypeNameHandling警告以及如何配置Json.NET以创建易受攻击的web API。 -
编写一个自定义转换器,查看实际属性并选择要使用的派生类,如下所述:使用json.net在没有类型信息的情况下反序列化多态json类。这避免了对额外
"$type"
属性的需要。
如果在JSON.NET serializer设置中使用以下设置,这应该会起作用:
var settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto};
这将把对象类型编码到JSON流中,这将帮助反序列化器在反序列化过程中确定要构造的特定对象类型。