如何序列化从Dictionary派生的类

我试图使用Json.Net将以下类与Json序列化/反序列化:

public class ChildDictionary:Dictionary { public string Name { get; set; } } 

我在这里 , 这里和这里找到了相关的信息,但没有一个具体涉及我们从Dictionary派生的这种情况的语法应该是什么样的。

员工自己与Json.Net成功序列化。 它看起来像这样:

 [JsonObject(MemberSerialization.OptIn)] public class Employee { [JsonProperty] public string Name { get; set; } [JsonProperty] public double Factor { get; set; } [JsonProperty] public List LoadBuilders = new List(); [JsonConstructor] public LoadCause(string name, double factor, List loadBuilders) { this.Name = name; this.DurationFactor = Factor; this.LoadBuilders = loadBuilders; } } 

只要我能在不丢失数据的情况下编写和阅读它,我不在乎Json最终会是什么样子

有关完成此任务的代码应该是什么样的建议? Custom JsonConverter或Attributes都是很好的解决方案。

因为您的字典具有复杂的键和其他属性,所以您需要使用自定义JsonConverter来序列化和反序列化此类。 下面是一个应该完成这项工作的转换器。 它分两部分处理序列化:首先它使用reflection来处理类上的任何读写属性,然后它将对象转换为字典接口来处理键值对。 后者作为具有KeyValue属性的对象数组写入JSON,以便管理复杂的键而无需跳过额外的箍。

 public class ComplexDictionaryConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary))); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { JObject obj = new JObject(); foreach (PropertyInfo prop in GetReadWriteProperties(value.GetType())) { object val = prop.GetValue(value); obj.Add(prop.Name, val != null ? JToken.FromObject(val, serializer) : new JValue(val)); } JArray array = new JArray(); foreach (var kvp in (IDictionary)value) { JObject item = new JObject(); item.Add("Key", JToken.FromObject(kvp.Key, serializer)); item.Add("Value", kvp.Value != null ? JToken.FromObject(kvp.Value, serializer) : new JValue(kvp.Value)); array.Add(item); } obj.Add("KVPs", array); obj.WriteTo(writer); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject obj = JObject.Load(reader); IDictionary dict = (IDictionary)Activator.CreateInstance(objectType); foreach (PropertyInfo prop in GetReadWriteProperties(objectType)) { JToken token = obj[prop.Name]; object val = token != null ? token.ToObject(prop.PropertyType, serializer) : null; prop.SetValue(dict, val); } JArray array = (JArray)obj["KVPs"]; foreach (JObject kvp in array.Children()) { K key = kvp["Key"].ToObject(serializer); V val = kvp["Value"].ToObject(serializer); dict.Add(key, val); } return dict; } private IEnumerable GetReadWriteProperties(Type type) { return type.GetProperties().Where(p => p.CanRead && p.CanWrite && !p.GetIndexParameters().Any()); } } 

要使用转换器,您可以使用[JsonConverter]属性标记您的类(确保通用参数与您的类inheritance的字典匹配):

 [JsonConverter(typeof(ComplexDictionaryConverter))] public class ChildDictionary : Dictionary { ... } 

这是一个演示完整往返的演示:

 class Program { static void Main(string[] args) { ChildDictionary dict = new ChildDictionary(); dict.Name = "Roster"; dict.Add(new Employee { Id = 22, Name = "Joe", HireDate = new DateTime(2012, 4, 17) }, 1923.07); dict.Add(new Employee { Id = 45, Name = "Fred", HireDate = new DateTime(2010, 8, 22) }, 1415.25); string json = JsonConvert.SerializeObject(dict, Formatting.Indented); Console.WriteLine(json); dict = JsonConvert.DeserializeObject(json); Console.WriteLine("Name: " + dict.Name); foreach (var kvp in dict) { Console.WriteLine("Employee Id: " + kvp.Key.Id); Console.WriteLine("Employee Name: " + kvp.Key.Name); Console.WriteLine("Employee Hire Date: " + kvp.Key.HireDate); Console.WriteLine("Amount: " + kvp.Value); Console.WriteLine(); } } } [JsonConverter(typeof(ComplexDictionaryConverter))] public class ChildDictionary : Dictionary { public string Name { get; set; } } public class Employee { public int Id { get; set; } public string Name { get; set; } public DateTime HireDate { get; set; } } 

输出:

 { "Name": "Roster", "KVPs": [ { "Key": { "Id": 22, "Name": "Joe", "HireDate": "2012-04-17T00:00:00" }, "Value": 1923.07 }, { "Key": { "Id": 45, "Name": "Fred", "HireDate": "2010-08-22T00:00:00" }, "Value": 1415.25 } ] } Name: Roster Employee Id: 22 Employee Name: Joe Employee Hire Date: 4/17/2012 12:00:00 AM Amount: 1923.07 Employee Id: 45 Employee Name: Fred Employee Hire Date: 8/22/2010 12:00:00 AM Amount: 1415.25 

小提琴: https : //dotnetfiddle.net/fTfoIk