如何在C#中实现通用的反序列化JSON任意属性修改方法?
需求:通用修改JSON任意属性的C#方法
现有文件内容
config/data.json
{ "background": false, "title": "XYZ", "object1": { "something1": -1, "something2": "auto", "something3": false, "something4": true }, "object2": { "something1": true, "something2": true, "something3": false, "something4": [ [5,0], [4,1] ] }, "object3": [ { "something1": null, "something2": null, "something3": "someString", "something4": "someString" } ] }
program.cs 实体类定义
// JSON反序列化所需的类 public class Object1 { public int something1 { get; set; } public string something2 { get; set; } public bool something3 { get; set; } public bool something4 { get; set; } } public class Object2 { public bool something1 { get; set; } public bool something2 { get; set; } public bool something3 { get; set; } public IList<IList<int>> something4 { get; set; } } public class Object3 { public object something1 { get; set; } public object something2 { get; set; } public string something3 { get; set; } public string something4 { get; set; } } public class Example { public bool background { get; set; } public string title { get; set; } public Object1 object1 { get; set; } public Object2 object2 { get; set; } public IList<Object3> object3 { get; set; } }
现有处理方法
private readonly static string rigJsonPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("config", "data.json")); public static Example ReadAndDeserialize() { string json = File.ReadAllText(rigJsonPath); Example ex = JsonSerializer.Deserialize<Rig.Xmrig>(json)!; return ex; } public static void SerializeAndWrite(Example ex) { string json = JsonSerializer.Serialize(ex); File.WriteAllText(rigJsonPath, json); } public static void ModifyXmrProperty(Example ex, string propertyName, object propertyValue) { switch (propertyName) { case "background": ex.background = (bool)propertyValue; break; case "title": ex.title = (string)propertyValue; break; case "object1.something1": ex.object1!.something1 = (int)propertyValue; break; // 等等,但这种方式无法覆盖所有属性 } }
核心需求
需要实现一个通用方法,接收参数后完成「JSON反序列化 → 修改指定字段(支持任意层级属性、嵌套对象、数组元素) → 序列化回写覆盖文件」的完整流程,避免为每个属性编写switch分支。
解决方案
方案1:使用JsonNode(.NET 6+ 推荐)
JsonNode是System.Text.Json原生支持的动态JSON操作API,无需依赖强类型类即可灵活修改任意节点:
private readonly static string rigJsonPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config", "data.json"); public static void ModifyJsonProperty(string propertyPath, object propertyValue) { // 读取并解析JSON为可操作节点 string jsonContent = File.ReadAllText(rigJsonPath); JsonNode rootNode = JsonNode.Parse(jsonContent)!; // 拆分属性路径(如"object3[0].something3"拆分为["object3[0]", "something3"]) string[] pathSegments = propertyPath.Split('.'); JsonNode currentNode = rootNode; // 遍历路径定位到目标节点的父级 for (int i = 0; i < pathSegments.Length - 1; i++) { string segment = pathSegments[i]; if (segment.Contains('[')) { // 处理数组索引,提取数组名和下标 string arrayName = segment.Substring(0, segment.IndexOf('[')); int index = int.Parse(segment.Substring(segment.IndexOf('[') + 1, segment.IndexOf(']') - segment.IndexOf('[') - 1)); currentNode = currentNode[arrayName]![index]; } else { currentNode = currentNode[segment]!; } } // 设置目标节点值 string targetSegment = pathSegments[^1]; if (targetSegment.Contains('[')) { string arrayName = targetSegment.Substring(0, targetSegment.IndexOf('[')); int index = int.Parse(segment.Substring(segment.IndexOf('[') + 1, segment.IndexOf(']') - segment.IndexOf('[') - 1)); currentNode[arrayName]![index] = JsonValue.Create(propertyValue); } else { currentNode[targetSegment] = JsonValue.Create(propertyValue); } // 格式化后回写文件 string updatedJson = rootNode.ToJsonString(new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(rigJsonPath, updatedJson); }
使用示例:
// 修改顶级布尔属性 ModifyJsonProperty("background", true); // 修改嵌套对象的数值属性 ModifyJsonProperty("object1.something1", 100); // 修改数组中对象的字符串属性 ModifyJsonProperty("object3[0].something3", "updatedString"); // 修改二维数组元素 ModifyJsonProperty("object2.something4[0][1]", 5);
方案2:反射处理强类型对象
如果必须基于已有的Example强类型类操作,可通过反射遍历属性路径:
private readonly static string rigJsonPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config", "data.json"); public static void ModifyStrongTypeProperty(string propertyPath, object propertyValue) { // 反序列化为强类型对象 Example ex = ReadAndDeserialize(); object currentObj = ex; Type currentType = typeof(Example); string[] pathSegments = propertyPath.Split('.'); for (int i = 0; i < pathSegments.Length - 1; i++) { string segment = pathSegments[i]; if (segment.Contains('[')) { // 处理数组索引 string arrayName = segment.Substring(0, segment.IndexOf('[')); int index = int.Parse(segment.Substring(segment.IndexOf('[') + 1, segment.IndexOf(']') - segment.IndexOf('[') - 1)); PropertyInfo arrayProp = currentType.GetProperty(arrayName)!; IList array = (IList)arrayProp.GetValue(currentObj)!; currentObj = array[index]; currentType = currentObj.GetType(); } else { // 遍历嵌套对象属性 PropertyInfo prop = currentType.GetProperty(segment)!; currentObj = prop.GetValue(currentObj)!; currentType = prop.PropertyType; } } // 设置目标属性值(自动转换类型) string targetSegment = pathSegments[^1]; if (targetSegment.Contains('[')) { string arrayName = targetSegment.Substring(0, targetSegment.IndexOf('[')); int index = int.Parse(segment.Substring(segment.IndexOf('[') + 1, segment.IndexOf(']') - segment.IndexOf('[') - 1)); PropertyInfo arrayProp = currentType.GetProperty(arrayName)!; IList array = (IList)arrayProp.GetValue(currentObj)!; Type elementType = arrayProp.PropertyType.GetGenericArguments()[0]; array[index] = Convert.ChangeType(propertyValue, elementType); } else { PropertyInfo targetProp = currentType.GetProperty(targetSegment)!; targetProp.SetValue(currentObj, Convert.ChangeType(propertyValue, targetProp.PropertyType)); } // 回写文件 SerializeAndWrite(ex); } // 修正原反序列化方法的泛型错误 public static Example ReadAndDeserialize() { string json = File.ReadAllText(rigJsonPath); return JsonSerializer.Deserialize<Example>(json)!; }
使用示例:
ModifyStrongTypeProperty("title", "NewAppTitle"); ModifyStrongTypeProperty("object2.something3", true); ModifyStrongTypeProperty("object3[0].something1", 456);
方案对比
- JsonNode方案:无需强类型类,支持动态JSON结构修改,代码简洁,适合JSON结构可能变动的场景。
- 反射方案:基于强类型实体,自带类型校验,适合JSON结构固定、需要强类型约束的场景。
内容的提问来源于stack exchange,提问作者Mikson
相关产品推荐
相关产品推荐

