如何实现包含/不包含私有属性的JSON序列化?
两种JSON序列化方案(包含/不包含私有属性)
针对你的需求,以下几种方案无需创建重复类,可在运行时灵活控制序列化行为:
方案1:使用Newtonsoft.Json(Json.NET)动态控制序列化成员
Newtonsoft.Json支持通过自定义契约解析器,动态决定哪些属性参与序列化,无需修改原类结构。
包含私有属性的序列化
创建自定义契约解析器,强制包含所有私有属性:
public class IncludePrivatePropertiesResolver : DefaultContractResolver { protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { // 获取类的所有属性(公有+私有) var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Select(p => base.CreateProperty(p, memberSerialization)) .ToList(); // 标记所有属性为可序列化 foreach (var prop in properties) { prop.ShouldSerialize = _ => true; prop.Writable = true; prop.Readable = true; } return properties; } }
使用示例:
var book = new Book(); // 生成包含私有属性的JSON var includePrivateSettings = new JsonSerializerSettings { ContractResolver = new IncludePrivatePropertiesResolver() }; string jsonWithPrivate = JsonConvert.SerializeObject(book, includePrivateSettings);
不包含私有属性的序列化
直接使用默认配置即可,默认只序列化公有属性:
string jsonWithoutPrivate = JsonConvert.SerializeObject(book);
方案2:使用System.Text.Json的自定义JsonTypeInfo
如果坚持使用System.Text.Json,可通过自定义类型信息解析器,动态添加私有属性到序列化列表:
包含私有属性的配置
var includePrivateOptions = new JsonSerializerOptions(); includePrivateOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(Book)) { // 反射获取所有私有属性并添加到序列化配置 var privateProperties = typeof(Book).GetProperties(BindingFlags.Instance | BindingFlags.NonPublic); foreach (var prop in privateProperties) { var propertyInfo = typeInfo.CreateJsonPropertyInfo(prop.PropertyType, prop.Name); propertyInfo.Get = obj => prop.GetValue(obj); propertyInfo.Set = (obj, value) => prop.SetValue(obj, value); typeInfo.Properties.Add(propertyInfo); } } } } };
使用示例:
string jsonWithPrivate = JsonSerializer.Serialize(book, includePrivateOptions);
不包含私有属性的配置
直接使用默认JsonSerializerOptions,默认只处理公有属性:
string jsonWithoutPrivate = JsonSerializer.Serialize(book);
方案3:用AutoMapper动态生成映射对象
通过AutoMapper在运行时动态映射到匿名类型或动态对象,避免手动编写重复类:
配置AutoMapper
var config = new MapperConfiguration(cfg => { // 映射到包含所有属性(包括私有)的动态类型 cfg.CreateMap<Book, dynamic>().ForAllMembers(opt => opt.MapFrom(src => typeof(Book).GetProperty(opt.DestinationMemberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(src))); // 映射到只包含公有属性的动态类型(默认行为,可省略) cfg.CreateMap<Book, ExpandoObject>(); }); var mapper = config.CreateMapper();
使用示例
// 生成包含私有属性的JSON var bookWithPrivate = mapper.Map<dynamic>(book); string jsonWithPrivate = JsonSerializer.Serialize(bookWithPrivate); // 生成不包含私有属性的JSON var bookWithoutPrivate = mapper.Map<ExpandoObject>(book); string jsonWithoutPrivate = JsonSerializer.Serialize(bookWithoutPrivate);
内容的提问来源于stack exchange,提问作者Angry Fox
相关产品推荐
相关产品推荐

