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

如何在Newtonsoft.Json.JObject中获取与设置嵌套数据并自动创建层级

如何用Newtonsoft.Json便捷创建多层级JSON结构并设置属性?

我用C#开发,和前端JavaScript交互时频繁使用Newtonsoft.Json的JObject类型。现在需要实现一个属性,将multipage.pages设置为字符串数组,但multipage元素可能不存在。想知道Newtonsoft.Json是否提供便捷方式,确保创建新元素时层级树中的所有父节点都自动存在?

现有尝试与问题

直接使用点号作为键的失败案例

尝试直接用带点号的字符串作为键,结果被当成了单个JSON键,而非层级结构:

JObject j = new JObject();
j["multipage.keepSave"] = true;
Console.WriteLine(j.ToString());

输出结果:

{
  "multipage.keepSave": true
}

手动判断父节点的繁琐方案

手动检查每个父节点是否存在,虽然能实现需求,但每个属性都要重复编写判断逻辑,代码冗余:

void Main() {
    Form f = new Form();
    Console.WriteLine(f.KeepSave);
    f.KeepSave = true;
    Console.WriteLine(f.KeepSave);
    f.KeepSave = false;
    Console.WriteLine(f.KeepSave);
    Console.WriteLine(f.Options.ToString());
}

public class Form {
    public JObject Options = new JObject();
    public bool KeepSave
    {
        get
        {
            JToken t = Options["multipage"];
            if(t == null)
                return false;
            return (bool)t["keepsave"]; 
        }
        set {
            JToken t = Options["multipage"];
            if(t == null)
                Options["multipage"] = t = new JObject();
            t["keepsave"] = value;
        }
    }
}

自定义通用方法的尝试

我自己编写了一个通用方法来处理层级路径的设置,简化了属性的setter逻辑:

void Main() {
    Form f = new Form();
    Console.WriteLine(f.KeepSave);
    f.KeepSave = true;
    Console.WriteLine(f.KeepSave);
    f.KeepSave = false;
    Console.WriteLine(f.KeepSave);
    Console.WriteLine(f.Options.ToString());
}

static public void SetJObject(JToken o, string path, object value) {
    List<string> p = path.Split('.').ToList();
    for(int i = 0; i < p.Count - 1; i++) {
        string name = p[i];
        JToken j = o[name];
        if(j == null)
            o[name] = j = new JObject();
        o = j;
    }
    o[p[p.Count - 1]] = JToken.FromObject(value);
}

public class Form {
    public JObject Options = new JObject();
    public bool KeepSave
    {
        get
        {
            JToken t = Options.SelectToken("multipage.keepsave");
            return t == null ? false : (bool)t; 
        }
        set {
            SetJObject(Options, "multipage.keepsave", value);
        }
    }
}

改进建议

1. 优化通用方法的健壮性

针对原方法的不足,增加参数校验、无效路径处理和类型冲突检查:

static public void SetJObject(JToken root, string path, object value) {
    if (root == null) throw new ArgumentNullException(nameof(root));
    if (string.IsNullOrEmpty(path)) throw new ArgumentException("路径不能为空", nameof(path));

    // 过滤路径中的空字符串,处理开头/结尾带点号的情况
    var segments = path.Split('.').Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
    if (segments.Count == 0) throw new ArgumentException("路径格式无效", nameof(path));

    JToken current = root;
    for (int i = 0; i < segments.Count - 1; i++) {
        var segment = segments[i];
        var next = current[segment];
        if (next == null) {
            next = new JObject();
            current[segment] = next;
        } else if (next.Type != JTokenType.Object) {
            // 父节点不是JObject,无法添加子节点,可根据需求抛出异常或做其他处理
            throw new InvalidOperationException($"路径中的节点 '{segment}' 不是JObject,无法创建子节点");
        }
        current = next;
    }

    current[segments.Last()] = JToken.FromObject(value);
}

2. 简化取值逻辑

利用SelectToken的扩展能力,结合空合并运算符简化getter:

public bool KeepSave
{
    get => Options.SelectToken("multipage.keepsave")?.ToObject<bool>() ?? false;
    set => SetJObject(Options, "multipage.keepsave", value);
}

3. 封装为扩展方法

将通用方法改成JToken的扩展方法,使用更直观:

public static class JTokenExtensions {
    public static void SetPathValue(this JToken root, string path, object value) {
        // 上述优化后的SetJObject逻辑放在此处
    }
}

调用方式简化为:

Options.SetPathValue("multipage.keepsave", value);

4. 强类型映射(可选)

如果配置结构稳定,直接定义强类型类,完全避免手动操作JObject,编译时类型检查更严格:

public class FormOptions {
    public MultipageConfig Multipage { get; set; } = new MultipageConfig();
}

public class MultipageConfig {
    public bool KeepSave { get; set; }
    public string[] Pages { get; set; } = Array.Empty<string>();
}

public class Form {
    public FormOptions Options { get; set; } = new FormOptions();

    public bool KeepSave {
        get => Options.Multipage.KeepSave;
        set => Options.Multipage.KeepSave = value;
    }

    public string[] Pages {
        get => Options.Multipage.Pages;
        set => Options.Multipage.Pages = value;
    }
}

序列化时直接使用JsonConvert.SerializeObject(Options)即可得到所需的JSON结构,无需手动处理层级创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 05:43:14