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

如何在JSON中引用其他值以避免重复粘贴?

解决nlohmann::json中JSON引用$ref的问题

nlohmann::json库本身不原生支持JSON Schema的$ref引用自动解析,所以直接写$ref的话,它只会把这个当作普通的键值对(一个包含"$ref"键的对象),不会自动替换成目标值。你可以通过以下几种方式解决:

1. 手动实现$ref解析逻辑

自己写递归函数遍历JSON结构,识别带有$ref的字段,根据引用路径找到目标值并替换。

比如针对你的场景,示例代码如下:

#include <nlohmann/json.hpp>
#include <vector>
#include <string>
#include <iostream>

using json = nlohmann::json;

// 递归解析$ref引用
void resolve_refs(json& target, const json& root) {
    if (target.is_object()) {
        // 检查当前对象是否是$ref引用
        if (target.contains("$ref") && target["$ref"].is_string()) {
            std::string ref_path = target["$ref"].get<std::string>();
            // 处理#/xxx/yyy格式的引用路径
            if (ref_path.substr(0, 2) == "#/") {
                std::vector<std::string> path_parts;
                size_t pos = 2;
                while (pos < ref_path.size()) {
                    size_t slash_pos = ref_path.find('/', pos);
                    if (slash_pos == std::string::npos) {
                        path_parts.push_back(ref_path.substr(pos));
                        break;
                    }
                    path_parts.push_back(ref_path.substr(pos, slash_pos - pos));
                    pos = slash_pos + 1;
                }
                // 从根节点开始查找目标值
                const json* current_node = &root;
                bool valid_ref = true;
                for (const auto& part : path_parts) {
                    if (current_node->contains(part)) {
                        current_node = &(*current_node)[part];
                    } else {
                        valid_ref = false;
                        break;
                    }
                }
                // 替换引用为目标值(如果引用有效)
                if (valid_ref) {
                    target = *current_node;
                }
            }
        } else {
            // 递归处理对象的每个子字段
            for (auto& [key, value] : target.items()) {
                resolve_refs(value, root);
            }
        }
    } else if (target.is_array()) {
        // 递归处理数组的每个元素
        for (auto& elem : target) {
            resolve_refs(elem, root);
        }
    }
}

int main() {
    // 你的示例JSON
    json raw_data = R"(
    {
        "loggingFile": "archive.txt",
        "someKey": [
            {
                "name": "task1",
                "loggingFile": {"$ref": "#/loggingFile"}
            },
            {
                "name": "task2",
                "loggingFile": {"$ref": "#/loggingFile"}
            }
        ]
    }
    )"_json;

    // 解析所有引用
    resolve_refs(raw_data, raw_data);

    // 输出处理后的结果
    std::cout << raw_data.dump(4) << std::endl;
    return 0;
}

这段代码会遍历JSON的所有节点,把带有$ref的对象替换成对应的目标值,处理后someKey数组里的每个loggingFile字段都会变成"archive.txt"字符串。

2. 预处理JSON文件

如果不想在代码里处理,可以用支持JSON Schema引用的工具提前把带$ref的JSON展开成普通JSON,再用nlohmann::json读取。比如用Python的jsonschema库或者专门的JSON引用展开工具,提前生成没有引用的JSON文件。

3. 使用自定义标识代替$ref

如果不想依赖$ref规范,可以自己定义一个标识(比如"__ref__"),然后在代码里识别这个键并替换。这样可以避免和任何库的默认行为冲突,逻辑和上面的手动解析类似,只是把判断"$ref"改成判断"__ref__"即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:02:40