如何自定义DefaultContractResolver实现JSON与多模型的属性映射?
自定义DefaultContractResolver解决跨模型JSON属性映射问题
当需要在不修改现有模型(不能重命名、添加特性)的前提下,实现JSON字段到不同模型属性的差异化映射时,常规的ResolvePropertyName方法无法区分属性所属的类型,此时可以通过重写DefaultContractResolver的CreateProperty方法来实现细粒度的映射控制。
实现思路
重写CreateProperty方法,通过MemberInfo.DeclaringType判断当前属性所属的模型类,再根据属性名称指定对应的JSON字段名,以此解决同一JSON字段对应不同模型属性的问题(比如JSON中的id对应Alarm.AlarmId和Setting.SettId)。
代码实现
自定义ContractResolver
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System.Reflection; public class CustomContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); // 处理Alarm类的属性映射 if (member.DeclaringType == typeof(Alarm)) { switch (member.Name) { case nameof(Alarm.AlarmId): property.PropertyName = "id"; break; case nameof(Alarm.AlarmName): property.PropertyName = "name"; break; case nameof(Alarm.RbcType): property.PropertyName = "type"; break; case nameof(Alarm.MinimumTolerated): property.PropertyName = "min"; break; case nameof(Alarm.MaximumTolerated): property.PropertyName = "max"; break; } } // 处理Setting类的属性映射 else if (member.DeclaringType == typeof(Setting)) { switch (member.Name) { case nameof(Setting.SettId): property.PropertyName = "id"; break; case nameof(Setting.IntValue): property.PropertyName = "value"; break; } } return property; } }
使用示例
// 反序列化 string json = @"{""parameter"": {""alarms"": [{""id"":1,""name"":""alarm1"",""type"":5,""min"":0,""max"":2}],""settings"": [{""id"":1,""name"":""setting1"",""description"":""something here"",""type"":1,""value"":2}]}}"; var serializerSettings = new JsonSerializerSettings { ContractResolver = new CustomContractResolver() }; var parameterModel = JsonConvert.DeserializeObject<Parameter>(json, serializerSettings); // 序列化 var parameterToSerialize = new Parameter { Alarms = new List<Alarm> { new Alarm { AlarmId = 1, AlarmName = "alarm1", RbcType = AlarmType.Type5, MinimumTolerated = 0, MaximumTolerated = 2 } }, Settings = new List<Setting> { new Setting { SettId = 1, Name = "setting1", Description = "something here", Type = SettingType.Type1, IntValue = 2 } } }; string serializedJson = JsonConvert.SerializeObject(parameterToSerialize, serializerSettings);
扩展说明
如果后续新增其他需要映射的模型,只需在CreateProperty方法中添加对应的类型判断分支和属性映射规则即可,全程无需修改原有模型代码,完全符合需求约束。
内容的提问来源于stack exchange,提问作者Jaime Oliveira
相关产品推荐
相关产品推荐

