问题
I have a Queue of an abstract class KVP. I queue 2 different objects which inherit from KVP. Everything works fine when I serialize the queue, but since KVP cannot be constructed it fails on deserialization.
If it was a single non generic object I could deserialize as dynamic, but I'm not sure how to deserialize a queue that could hold both events and IDs.
Sample code:
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;
}
}
回答1:
You could
Enable TypeNameHandling (in both serialization and deserialization):
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; var serializedText= JsonConvert.SerializeObject(mQueue, settings);
And then later
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; var mQueue = JsonConvert.DeserializeObject<Queue<T>>(serializedText, settings);
This adds an extra
"$type"
property to your polymorphic classes, as is described here.Before choosing this solution, for a discussion of possible security concerns using
TypeNameHandling
, see TypeNameHandling caution in Newtonsoft Json and How to configure Json.NET to create a vulnerable web API.Write a custom converter that looks at the actual properties and chooses which derived class to use, as is discussed here: Deserializing polymorphic json classes without type information using json.net. This avoids the need for the extra
"$type"
property.
回答2:
This should work if you use the following setting in the JSON.NET serialiser settings:
var settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto};
This will encode the object type into the JSON stream, which will help the deserializer determined the specific object type to construct during de-serialization.
来源:https://stackoverflow.com/questions/29214407/deserializing-abstract-queuet-in-json