在C#和Blazor中遍历this关键字并序列化为JSON的方法
解决方案:Blazor页面中动态序列化
this的成员 问题原因
JsonConvert.SerializeObject(this)返回空字符串,核心原因是:
- Blazor页面继承的
ComponentBase包含大量内部/受保护的框架属性,默认情况下Json.NET只会序列化公共属性,如果你要序列化的是私有字段,会被直接跳过。 - 即使开启非公共成员序列化,默认也会包含父类(
ComponentBase)的冗余属性,导致要么为空,要么序列化一堆无用内容。
直接foreach遍历this报错,是因为页面类并非集合类型,没有实现IEnumerable接口,不能直接遍历实例本身。
可行方案
方案1:反射过滤当前类成员,构建字典后序列化
通过反射获取当前页面类自己定义的字段/属性,过滤掉父类的框架成员,再序列化,这是最精准的方式。
示例代码(假设你的页面类是Pages.Index):
using System.Reflection; using Newtonsoft.Json; // 在页面的方法(比如按钮点击事件)中执行 var targetMembers = this.GetType() // 获取当前实例的所有字段:公共+非公共 .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) // 只保留当前类定义的字段,排除ComponentBase等父类的成员 .Where(member => member.DeclaringType == typeof(Index)) // 转成字典,键为字段名,值为字段值 .ToDictionary(member => member.Name, member => member.GetValue(this)); // 序列化字典 var jsonResult = JsonConvert.SerializeObject(targetMembers, Formatting.Indented);
如果要序列化属性而非字段,把GetFields换成GetProperties即可:
var targetMembers = this.GetType() .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(member => member.DeclaringType == typeof(Index)) .ToDictionary(member => member.Name, member => member.GetValue(this));
方案2:配置JsonSerializer,仅序列化当前类成员
通过自定义序列化配置,让Json.NET包含非公共成员,同时只处理当前页面类的成员:
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; var serializerSettings = new JsonSerializerSettings { Formatting = Formatting.Indented, ContractResolver = new DefaultContractResolver { // 允许序列化非公共成员 DefaultMembersSearchFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, // 只序列化当前类定义的成员,忽略父类 ShouldSerialize = (member) => member.DeclaringType == typeof(Index) } }; var jsonResult = JsonConvert.SerializeObject(this, serializerSettings);
方案3:遍历this的成员(实现类似foreach的效果)
如果需要遍历成员而非序列化,同样用反射获取成员集合后遍历:
using System.Reflection; // 获取当前类的所有字段 var fields = this.GetType() .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(m => m.DeclaringType == typeof(Index)); foreach (var field in fields) { string memberName = field.Name; object memberValue = field.GetValue(this); // 这里处理每个成员,比如打印、存入集合等 }
注意事项
- 如果你用的是System.Text.Json而非Newtonsoft.Json,配置逻辑类似,需要设置
JsonSerializerOptions的IncludeFields和自定义JsonConverter来过滤父类成员。 - 反射会带来轻微的性能开销,但对于Blazor页面的场景(非高频调用)完全可以忽略。
内容的提问来源于stack exchange,提问作者freyfrey01
相关产品推荐
相关产品推荐

