从JSON保存和加载不同类型的C#列表

时间:2018-08-21 16:02:37

标签: c# json list serialization deserialization

我正在使用JSON对c#中的列表进行序列化和反序列化。如果列表由单一类型的对象组成,则一切正常。我的目标是找到一种存储不同类型的对象的列表(或队列或类似对象)的方法,我可以在以后加载和迭代并对其执行操作。我可以将序列化分解为多个列表,但是按照对象被添加的顺序迭代这些对象很重要,因此使它们全部成为同一数据结构的一部分是理想的。

我试图拥有一个它们都继承的DataModelBase类,并具有一个DataModelBase类型的列表,该类型在运行时和保存时都起作用,但是load / deserialize函数却无法起作用。我也尝试使用接口,并将自定义参数传递给我的反序列化调用,但这导致我的Unity应用程序崩溃。有没有更好的方法可以解决我要达到的目标?

这是我的加载函数:

public static T LoadData<T>(string path)
    {
        using (var reader = new StreamReader(path))
        {
            var fileContents = reader.ReadToEnd();
            reader.Close();
            reader.Dispose();
            return JsonConvert.DeserializeObject<T>(fileContents);
        }
    }

尝试将列表中的条目转换为类类型时,通常会遇到以下错误:RuntimeBinderException:无法隐式将类型Newtonsoft.Json.Linq.JObject' to转换为我试图转换为的类型'

2 个答案:

答案 0 :(得分:1)

我将使用TypeNameHandling设置将类型数据保存在保存的JSON中。这很可能会解决您所看到的反序列化问题。

从链接的文档中:

Stockholder stockholder = new Stockholder
{
    FullName = "Steve Stockholder",
    Businesses = new List<Business>
    {
        new Hotel
        {
            Name = "Hudson Hotel",
            Stars = 4
        }
    }
};

string jsonTypeNameAll = JsonConvert.SerializeObject(stockholder, Formatting.Indented, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
});

Console.WriteLine(jsonTypeNameAll);
// {
//   "$type": "Newtonsoft.Json.Samples.Stockholder, Newtonsoft.Json.Tests",
//   "FullName": "Steve Stockholder",
//   "Businesses": {
//     "$type": "System.Collections.Generic.List`1[[Newtonsoft.Json.Samples.Business, Newtonsoft.Json.Tests]], mscorlib",
//     "$values": [
//       {
//         "$type": "Newtonsoft.Json.Samples.Hotel, Newtonsoft.Json.Tests",
//         "Stars": 4,
//         "Name": "Hudson Hotel"
//       }
//     ]
//   }
// }

string jsonTypeNameAuto = JsonConvert.SerializeObject(stockholder, Formatting.Indented, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});

Console.WriteLine(jsonTypeNameAuto);
// {
//   "FullName": "Steve Stockholder",
//   "Businesses": [
//     {
//       "$type": "Newtonsoft.Json.Samples.Hotel, Newtonsoft.Json.Tests",
//       "Stars": 4,
//       "Name": "Hudson Hotel"
//     }
//   ]
// }

// for security TypeNameHandling is required when deserializing
Stockholder newStockholder = JsonConvert.DeserializeObject<Stockholder>(jsonTypeNameAuto, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});

Console.WriteLine(newStockholder.Businesses[0].GetType().Name);
// Hotel

答案 1 :(得分:0)

将json解析为Dynamic。它应该为您提供所需的灵活性,但可能会有点慢

Deserialize json object into dynamic object using Json.net

或者您可以使用多态性

what's the difference between inheritance and polymorphism?