如何在C#中修改JSON文件的嵌套对象与数组值?
修改JSON嵌套对象与数组元素的C#实现
针对当前仅能修改JSON顶层字段的问题,以下是几种基于Newtonsoft.Json(Json.NET)的解决方案,可实现嵌套对象、深层属性及数组元素的修改:
原问题回顾
JSON结构
{ "externalReference": "Integrator Reference", "proposalType": "Private Individual", "dealer": { "dealerID": 9344 }, "financeDetails": { "type": "HP", "cashDeposit": 111, "settlement": 11, "partExchange": 22, "term": 72, "apr": 12.9, "loanamount": 0.0, "distanceSelling": true, "vehicleAsset": { "type": "Used", "class": "Car", "source": "UK", "purpose": "Social", "vrm": "string", "dateOfRegistration": "16-10-2020", "manufacturer": "string", "model": "string", "derivative": "string", "capCode": "ALGU21S164SDTA", "CurrentMileage": 25000, "vatRate": 20, "netValue": 5000 }, "additionalAssets": [ { "type": "MOT", "netValue": 250, "vatRate": 20, "description": "string" }, { "type": "BCI_VAT", "netValue": 350, "vatRate": 5, "description": "string" } ] } }
现有代码
public static void CallRequest(string fieldName, string enteredFieldValue) { string sendProposalRequestSuccess = File.ReadAllText(sendProposalUnityJSONFile); dynamic jsonObj = JsonConvert.DeserializeObject(sendProposalRequestSuccess); jsonObj[fieldName] = enteredFieldValue; string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented); File.WriteAllText(sendProposalUnityJSONFile, output); }
方案1:直接通过dynamic层级访问
利用dynamic对象的.运算符直接访问嵌套属性,数组则通过索引定位元素:
修改嵌套对象属性
public static void CallRequest(object enteredFieldValue) { string json = File.ReadAllText(sendProposalUnityJSONFile); dynamic jsonObj = JsonConvert.DeserializeObject(json); // 修改dealer下的dealerID jsonObj.dealer.dealerID = 12345; // 修改financeDetails下的cashDeposit jsonObj.financeDetails.cashDeposit = 200; // 修改更深层的vehicleAsset.netValue jsonObj.financeDetails.vehicleAsset.netValue = 6000; string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented); File.WriteAllText(sendProposalUnityJSONFile, output); }
修改数组元素
public static void CallRequest(object enteredFieldValue) { string json = File.ReadAllText(sendProposalUnityJSONFile); dynamic jsonObj = JsonConvert.DeserializeObject(json); // 修改数组第一个元素的netValue jsonObj.financeDetails.additionalAssets[0].netValue = 300; // 替换数组第二个元素 jsonObj.financeDetails.additionalAssets[1] = new { type = "BCI_VAT", netValue = 400, vatRate = 5, description = "Updated Asset" }; string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented); File.WriteAllText(sendProposalUnityJSONFile, output); }
方案2:支持路径字符串的通用修改方法
如果需要通过传入路径字符串(如"dealer.dealerID"、"financeDetails.additionalAssets[0].netValue")动态修改,可实现路径解析逻辑:
public static void CallRequest(string fieldPath, object enteredFieldValue) { string json = File.ReadAllText(sendProposalUnityJSONFile); dynamic jsonObj = JsonConvert.DeserializeObject(json); // 拆分路径段,处理普通节点和数组索引 var segments = new List<string>(); int pos = 0; while (pos < fieldPath.Length) { if (fieldPath[pos] == '[') { // 提取数组索引段(如[0]) int closeBracket = fieldPath.IndexOf(']', pos); segments.Add(fieldPath.Substring(pos, closeBracket - pos + 1)); pos = closeBracket + 1; // 跳过后续的.(如果存在) if (pos < fieldPath.Length && fieldPath[pos] == '.') pos++; } else { // 提取普通节点段 int nextDot = fieldPath.IndexOf('.', pos); nextDot = nextDot == -1 ? fieldPath.Length : nextDot; segments.Add(fieldPath.Substring(pos, nextDot - pos)); pos = nextDot + 1; } } // 遍历路径段,定位到目标父节点 dynamic current = jsonObj; for (int i = 0; i < segments.Count - 1; i++) { string seg = segments[i]; if (seg.StartsWith('[') && seg.EndsWith(']')) { // 处理数组索引 int index = int.Parse(seg.Substring(1, seg.Length - 2)); current = current[index]; } else { // 处理普通对象属性 current = current[seg]; } } // 设置目标值 string lastSeg = segments[^1]; if (lastSeg.StartsWith('[') && lastSeg.EndsWith(']')) { int index = int.Parse(lastSeg.Substring(1, lastSeg.Length - 2)); current[index] = enteredFieldValue; } else { current[lastSeg] = enteredFieldValue; } string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented); File.WriteAllText(sendProposalUnityJSONFile, output); } // 调用示例 CallRequest("dealer.dealerID", 12345); CallRequest("financeDetails.vehicleAsset.netValue", 6000); CallRequest("financeDetails.additionalAssets[0].netValue", 300); CallRequest("financeDetails.additionalAssets[1]", new { type = "BCI_VAT", netValue = 400, vatRate = 5, description = "Updated Asset" });
方案3:强类型模型修改(更安全可靠)
如果JSON结构固定,建议定义对应的C#模型类,通过强类型操作避免dynamic的类型隐患:
定义模型类
public class ProposalRequest { public string externalReference { get; set; } public string proposalType { get; set; } public Dealer dealer { get; set; } public FinanceDetails financeDetails { get; set; } } public class Dealer { public int dealerID { get; set; } } public class FinanceDetails { public string type { get; set; } public int cashDeposit { get; set; } public int settlement { get; set; } public int partExchange { get; set; } public int term { get; set; } public double apr { get; set; } public double loanamount { get; set; } public bool distanceSelling { get; set; } public VehicleAsset vehicleAsset { get; set; } public List<AdditionalAsset> additionalAssets { get; set; } } public class VehicleAsset { public string type { get; set; } public string @class { get; set; } // 转义关键字class public string source { get; set; } public string purpose { get; set; } public string vrm { get; set; } public string dateOfRegistration { get; set; } public string manufacturer { get; set; } public string model { get; set; } public string derivative { get; set; } public string capCode { get; set; } public int CurrentMileage { get; set; } public int vatRate { get; set; } public int netValue { get; set; } } public class AdditionalAsset { public string type { get; set; } public int netValue { get; set; } public int vatRate { get; set; } public string description { get; set; } }
强类型修改代码
public static void UpdateProposal<T>(Expression<Func<ProposalRequest, T>> propertySelector, T value) { string json = File.ReadAllText(sendProposalUnityJSONFile); ProposalRequest request = JsonConvert.DeserializeObject<ProposalRequest>(json); // 解析表达式定位目标属性 MemberExpression memberExpr = (MemberExpression)propertySelector.Body; PropertyInfo targetProperty = (PropertyInfo)memberExpr.Member; object targetObject = request; // 遍历嵌套层级,找到属性所在的对象 while (memberExpr.Expression is MemberExpression parentExpr) { PropertyInfo parentProperty = (PropertyInfo)parentExpr.Member; targetObject = parentProperty.GetValue(targetObject); memberExpr = parentExpr; } // 设置属性值 targetProperty.SetValue(targetObject, value); string output = JsonConvert.SerializeObject(request, Formatting.Indented); File.WriteAllText(sendProposalUnityJSONFile, output); } // 调用示例 UpdateProposal(req => req.dealer.dealerID, 12345); UpdateProposal(req => req.financeDetails.cashDeposit, 200); UpdateProposal(req => req.financeDetails.additionalAssets[0].netValue, 300);
内容的提问来源于stack exchange,提问作者kieranm007
相关产品推荐
相关产品推荐

