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

如何解析超出内存的JSON?能否用Nlohmann/标准库实现指定索引读取?

处理超大型JSON多维数组的内存友好方案(仅用Nlohmann JSON或标准库)

用Nlohmann JSON实现:SAX流式解析

Nlohmann JSON支持SAX风格的事件驱动解析,无需加载整个JSON到内存,可精准提取指定索引区间的数组元素。核心思路是自定义SAX处理器,跟踪数组层级和当前元素索引,仅在索引落在目标区间时解析并保存元素。

示例代码

#include <nlohmann/json.hpp>
#include <fstream>
#include <vector>

using json = nlohmann::json;

class ArrayRangeExtractor : public json::sax_parser {
public:
    ArrayRangeExtractor(size_t start, size_t end) 
        : target_start(start), target_end(end), current_array_level(0), current_element_idx(0) {}

    bool start_array() override {
        current_array_level++;
        if (current_array_level == 1) {
            current_element_idx = 0;
        }
        return true;
    }

    bool end_array() override {
        current_array_level--;
        return true;
    }

    bool start_object() override {
        if (is_target_element()) {
            temp_element = json::object();
            return true;
        }
        return false;
    }

    bool end_object() override {
        if (is_target_element()) {
            result.push_back(std::move(temp_element));
            current_element_idx++;
            return true;
        }
        return false;
    }

    bool start_array_element() override {
        if (is_target_element()) {
            temp_element = json::array();
            return true;
        }
        return false;
    }

    bool end_array_element() override {
        if (is_target_element()) {
            result.push_back(std::move(temp_element));
            current_element_idx++;
            return true;
        }
        return false;
    }

    bool string(std::string&& s) override {
        if (is_target_element()) {
            result.push_back(std::move(s));
            current_element_idx++;
        }
        return true;
    }

    bool number_integer(long long i) override {
        if (is_target_element()) {
            result.push_back(i);
            current_element_idx++;
        }
        return true;
    }

    std::vector<json> get_result() {
        return std::move(result);
    }

private:
    bool is_target_element() {
        return current_array_level == 1 && current_element_idx >= target_start && current_element_idx <= target_end;
    }

    size_t target_start;
    size_t target_end;
    size_t current_array_level;
    size_t current_element_idx;
    std::vector<json> result;
    json temp_element;
};

int main() {
    std::ifstream large_json("large_array.json");
    ArrayRangeExtractor extractor(1000, 2000); // 提取索引1000到2000的元素

    json::sax_parse(large_json, &extractor);

    auto target_elements = extractor.get_result();
    // 处理提取到的元素
    return 0;
}

说明

  • 处理器仅跟踪最外层数组的元素索引,非目标元素的内部结构会直接跳过,不会占用额外内存。
  • 需根据实际JSON元素类型,补充重写对应的SAX方法(如number_float、boolean等)。

用C++标准库实现:手动流式解析

不依赖第三方库时,可直接用标准库文件流手动解析JSON结构,跳过不需要的元素,仅读取目标区间内容。核心是处理嵌套结构和转义字符,准确识别元素边界。

示例代码

#include <fstream>
#include <vector>
#include <string>
#include <cctype>

void skip_whitespace(std::ifstream& in) {
    char c;
    while (in.get(c) && std::isspace(c));
    in.putback(c);
}

size_t find_element_end(const std::string& content, size_t start) {
    size_t pos = start;
    int nested = 0;
    bool in_string = false;
    char prev = '\0';

    while (pos < content.size()) {
        char c = content[pos];
        if (in_string) {
            if (c == '"' && prev != '\\') in_string = false;
        } else {
            if (c == '"') in_string = true;
            else if (c == '[' || c == '{') nested++;
            else if (c == ']' || c == '}') {
                if (nested == 0) break;
                nested--;
            } else if (c == ',' && nested == 0) break;
        }
        prev = c;
        pos++;
    }
    return pos;
}

std::vector<std::string> extract_array_range(std::ifstream& in, size_t start_idx, size_t end_idx) {
    std::vector<std::string> result;
    skip_whitespace(in);

    char c;
    in.get(c);
    if (c != '[') return result;

    size_t current_idx = 0;
    while (true) {
        skip_whitespace(in);
        in.get(c);
        in.putback(c);

        if (c == ']') break;

        std::string element_content;
        char temp;
        while (in.get(temp)) {
            element_content += temp;
            size_t end_pos = find_element_end(element_content, 0);
            if (end_pos < element_content.size()) {
                std::string remaining = element_content.substr(end_pos);
                for (auto it = remaining.rbegin(); it != remaining.rend(); ++it) in.putback(*it);
                element_content = element_content.substr(0, end_pos);
                break;
            }
        }

        if (current_idx >= start_idx && current_idx <= end_idx) {
            result.push_back(element_content);
        }

        if (current_idx > end_idx) break;

        current_idx++;
        skip_whitespace(in);
        in.get(c);
        if (c != ',') in.putback(c);
    }

    return result;
}

int main() {
    std::ifstream large_json("large_array.json");
    auto target_elements = extract_array_range(large_json, 1000, 2000);

    for (const auto& elem_str : target_elements) {
        json elem = json::parse(elem_str);
        // 处理元素
    }

    return 0;
}

说明

  • 通过逐字符读取文件,手动跟踪JSON嵌套结构和字符串转义,准确识别每个元素边界。
  • 仅保存目标区间的元素字符串,后续可按需解析成JSON对象,内存消耗仅取决于目标元素数量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 22:15:52