Json.NET – CustomCreationConverter中单个属性的默认反序列化行为

在下面的场景中,当遇到我反序列化的类型中存在的JSON属性时,如何让CrazyItemConverter像往常一样继续?

我有一些看起来像这样的JSON:

 { "Item":{ "Name":"Apple", "Id":null, "Size":5, "Quality":2 } } 

JSON被反序列化为一个看起来像这样的类:

 [JsonConverter(typeof(CrazyItemConverter))] public class Item { [JsonConverter(typeof(CrazyStringConverter))] public string Name { get; set; } public Guid? Id { get; set; } [JsonIgnore] public Dictionary CustomFields { get { if (_customFields == null) _customFields = new Dictionary(); return _customFields; } } ... } 

CrazyItemConverter填充已知属性的值,并将未知属性放在CustomFields中。 其中的ReadJson看起来像这样:

 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var outputObject = Create(objectType); var objProps = objectType.GetProperties().Select(p => p.Name).ToArray(); while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) { string propertyName = reader.Value.ToString(); if (reader.Read()) { if (objProps.Contains(propertyName)) { // No idea :( // serializer.Populate(reader, outputObject); } else { outputObject.AddProperty(propertyName, reader.Value); } } } } return outputObject; } 

在反序列化期间,当CrazyItemConverter遇到已知属性时,我希望它像通常那样运行。 意思是,尊重[JsonConverter(typeof(CrazyStringConverter))][JsonConverter(typeof(CrazyStringConverter))]

我使用下面的代码来设置已知属性但是,它会抛出nullables上的exception并且不尊重我的其他JsonConverters。

 PropertyInfo pi = outputObject.GetType().GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType); pi.SetValue(outputObject, convertedValue, null); 

有任何想法吗?

更新:我已经学会了serializer.Populate(reader, outputObject); 是如何反序列化整个事情,但如果你想要逐个属性的默认function似乎不起作用。

如果我正确理解,您的CrazyItemConverter存在,以便您可以将JSON中的已知属性反序列化为强类型属性,同时仍然保留可能在JSON中的“额外”字段到字典中。

事实certificate,Json.Net已经内置了此function(自5.0版本5开始),因此您不需要疯狂的转换器。 相反,您只需要使用[JsonExtensionData]属性标记字典。 (有关更多信息,请参阅作者的博客 。)

所以你的Item类看起来像这样:

 public class Item { [JsonConverter(typeof(CrazyStringConverter))] public string Name { get; set; } public Guid? Id { get; set; } [JsonExtensionData] public Dictionary CustomFields { get { if (_customFields == null) _customFields = new Dictionary(); return _customFields; } private set { _customFields = value; } } private Dictionary _customFields; } 

然后你可以正常反序列化它。 演示:

 class Program { static void Main(string[] args) { string json = @" { ""Item"": { ""Name"":""Apple"", ""Id"":""4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac"", ""Size"":5, ""Quality"":2 } }"; Item item = JsonConvert.DeserializeObject(json).Item; Console.WriteLine("Name: " + item.Name); Console.WriteLine("Id: " + item.Id); foreach (KeyValuePair kvp in item.CustomFields) { Console.WriteLine(kvp.Key + ": " + kvp.Value); } } } public class Wrapper { public Item Item { get; set; } } class CrazyStringConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(string); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JToken token = JToken.Load(reader); // Reverse the string just for fun return new string(token.ToString().Reverse().ToArray()); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } 

输出:

 Name: elppA Id: 4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac Size: 5 Quality: 2