You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Newtonsoft.Json修改JObject中的嵌套属性值?

问题描述

我有如下结构的config.json:

{
  "Field": {
    "FieldKey1": "FieldValue1",
    "FieldKey2": "FieldValue2"
  },
  "List": [
    "ListEntry1",
    "ListEntry2"
  ],
  "UnnestedKey": "UnnestedValue"
}

通过以下代码可以正常读取嵌套值:

var x = await ConfigUtils.Get(configPath, "Field.FieldKey1");
Console.WriteLine(x.ToString());

对应的Get方法实现:

using Newtonsoft.Json;

public static async Task<JToken> Get(string filePath, string key)
{
    JObject jObject = await GetJObject(filePath);
    
    return jObject.SelectToken(key)
           ?? throw new KeyNotFoundException($"Key \"{key}\" doesn't exist in {filePath}.");
}
    
private static async Task<JObject> GetJObject(string filePath)
{
    string jsonString = await File.ReadAllTextAsync(filePath);
    
    JObject jObject = JObject.Parse(jsonString);
    
    return jObject;
}

这段代码能正确输出FieldValue1。

但调用以下代码修改嵌套值时出现问题:

await ConfigUtils.UpdateValue(configPath, "Field.FieldKey1", "NewValue");

对应的UpdateValue方法实现:

using Newtonsoft.Json;

public static async Task UpdateValue(string filePath, string key, string value)
{
    JObject jObject = await GetJObject(filePath);

    jObject.AddOrReplace(key, value);

    await WriteJObject(jObject, filePath);
}

执行后会新增一个名为Field.FieldKey1的顶级键,而非修改Field下的FieldKey1的值。

我知道需要用jObject.SelectToken(key)来定位嵌套节点,但不清楚后续如何修改,对JToken、JProperty、JObject的使用感到困惑,请问该如何修改UpdateValue方法以支持嵌套值的修改?

解决方案

问题出在AddOrReplace方法会把带点的键当作完整的顶级键名,而非解析为嵌套路径。要修改嵌套值,需先通过SelectToken定位到目标节点,再替换其值。

修改后的UpdateValue方法如下:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static async Task UpdateValue(string filePath, string key, string value)
{
    JObject jObject = await GetJObject(filePath);
    
    // 定位到目标嵌套节点
    JToken targetToken = jObject.SelectToken(key);
    if (targetToken == null)
    {
        throw new KeyNotFoundException($"Key \"{key}\" doesn't exist in {filePath}.");
    }
    
    // 根据目标节点类型处理值替换
    if (targetToken is JProperty property)
    {
        // 若为属性节点,直接替换其值
        property.Value = value;
    }
    else
    {
        // 若为其他类型节点(如JValue),替换整个节点内容
        targetToken.Replace(JToken.FromObject(value));
    }
    
    await WriteJObject(jObject, filePath);
}

// 补充WriteJObject方法实现(若之前未定义)
private static async Task WriteJObject(JObject jObject, string filePath)
{
    string updatedJson = jObject.ToString(Formatting.Indented);
    await File.WriteAllTextAsync(filePath, updatedJson);
}

关键说明

  • 用SelectToken定位节点:和读取逻辑一致,通过SelectToken(key)找到嵌套目标节点,避免将带点的键当作单一顶级键。
  • 区分节点类型处理:针对JProperty(键值对属性)直接修改Value;针对JValue等节点使用Replace方法替换内容。
  • 异常处理:若指定键路径不存在,抛出对应异常,和读取逻辑保持统一。

修改后,调用UpdateValue(configPath, "Field.FieldKey1", "NewValue")即可正确修改Field下FieldKey1的值,不会新增顶级键。

内容的提问来源于stack exchange,提问作者user21526533

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 10:07:39