使用catch all dictionary属性将json序列化为一个对象

我想使用JSON.net反序列化为对象,但将未映射的属性放在字典属性中。 可能吗?

比如给json,

{one:1,two:2,three:3} 

和c#类:

 public class Mapped { public int One {get; set;} public int Two {get; set;} public Dictionary TheRest {get; set;} } 

JSON.NET可以反序列化为值为1 = 1,2 = 1的实例,TheRest = Dictionary {{“three,3}}

您可以创建CustomCreationConverter来执行您需要执行的操作。 这是一个样本(相当难看,但演示了你可能想要这样做):

 namespace JsonConverterTest1 { public class Mapped { private Dictionary _theRest = new Dictionary(); public int One { get; set; } public int Two { get; set; } public Dictionary TheRest { get { return _theRest; } } } public class MappedConverter : CustomCreationConverter { public override Mapped Create(Type objectType) { return new Mapped(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var mappedObj = new Mapped(); var objProps = objectType.GetProperties().Select(p => p.Name.ToLower()).ToArray(); //return base.ReadJson(reader, objectType, existingValue, serializer); while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) { string readerValue = reader.Value.ToString().ToLower(); if (reader.Read()) { if (objProps.Contains(readerValue)) { PropertyInfo pi = mappedObj.GetType().GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType); pi.SetValue(mappedObj, convertedValue, null); } else { mappedObj.TheRest.Add(readerValue, reader.Value); } } } } return mappedObj; } } public class Program { static void Main(string[] args) { string json = "{'one':1, 'two':2, 'three':3, 'four':4}"; Mapped mappedObj = JsonConvert.DeserializeObject(json, new MappedConverter()); Console.WriteLine(mappedObj.TheRest["three"].ToString()); Console.WriteLine(mappedObj.TheRest["four"].ToString()); } } } 

因此,在反序列化JSON字符串后,mappedObj的输出将是一个对象, One填充了OneTwo属性,并将其他所有内容放入Dictionary 。 当然,我将One和Two值硬编码为int ,但我认为这certificate了你如何去做。

我希望这有帮助。

编辑 :我更新了代码,使其更通用。 我没有完全测试它,所以在某些情况下它会失败,但我认为它会让你大部分都在那里。

最简单的方法是使用JsonExtensionData属性来定义catch all dictionary。

Json.Net文档中的示例:

 public class DirectoryAccount { // normal deserialization public string DisplayName { get; set; } // these properties are set in OnDeserialized public string UserName { get; set; } public string Domain { get; set; } [JsonExtensionData] private IDictionary _additionalData; [OnDeserialized] private void OnDeserialized(StreamingContext context) { // SAMAccountName is not deserialized to any property // and so it is added to the extension data dictionary string samAccountName = (string)_additionalData["SAMAccountName"]; Domain = samAccountName.Split('\\')[0]; UserName = samAccountName.Split('\\')[1]; } public DirectoryAccount() { _additionalData = new Dictionary(); } } string json = @"{ 'DisplayName': 'John Smith', 'SAMAccountName': 'contoso\\johns' }"; DirectoryAccount account = JsonConvert.DeserializeObject(json); Console.WriteLine(account.DisplayName); // John Smith Console.WriteLine(account.Domain); // contoso Console.WriteLine(account.UserName); // johns