关于 c#:在 Json 中反序列化抽象 Queue< T >

Deserializing abstract Queue<T> in Json

本问题已经有最佳答案,请猛点这里访问。

我有一个抽象类 KVP 的队列。我将 2 个从 KVP 继承的不同对象排队。当我序列化队列时一切正常,但由于无法构建 KVP,它在反序列化时失败。

如果它是单个非通用对象,我可以将其反序列化为动态对象,但我不确定如何反序列化一个可以同时保存事件和 ID 的队列。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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(在序列化和反序列化中):

    1
    2
        var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
        var serializedText= JsonConvert.SerializeObject(mQueue, settings);

    后来

    1
    2
        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 序列化器设置中使用以下设置,这应该可以工作:

    1
    var settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto};

    这会将对象类型编码到 JSON 流中,这将有助于反序列化器确定在反序列化过程中要构造的特定对象类型。