c++ - 如何在 JSON 中创建文件层次结构表示
问题描述
我第一次使用https://github.com/nlohmann/json,我必须像这样创建文件层次结构:
{
"Files": [
{
"Name": "Test.txt",
"Size": "27 B",
"Path": "D:\\Projects\\Test.txt"
},
...
],
"Children": [
{
"Name": "SubProjects",
"Files": [
{
"Name": "SubTest.txt",
"Size": "2 B",
"Path": "D:\\Projects\\SubProjects\\SubTest.txt"
},
...
],
"Children": [
....
]
},
{
"Name": "SubProjects3",
"Files": [],
"Children": []
},
...
]}
现在我在嵌套节点中添加信息时遇到问题。我试图通过搜索新键“级别”来解决这个问题,并试图找到这个键等于我需要的级别,但它仍然不起作用。我的代码:
#include <iostream>
#include <conio.h>
#include <nlohmann/json.hpp>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <experimental/filesystem>
using namespace std;
using json = nlohmann::json;
namespace fs = std::experimental::filesystem;
void DisplayFileInfo(const fs::v1::directory_entry& entry, fs::v1::path& filename , json &j_main,int level)
{
json j_file;
j_file["Name"] = filename.string();
j_file["Size"] = fs::file_size(entry);
j_file["Path"] = fs::absolute(filename).string();
for ( auto& obj : j_main) {
if (obj["Level"] == level) {
obj["Files"].push_back(j_file);
}
}
}
void DisplayFolderInfo(const fs::v1::directory_entry& entry, fs::v1::path& filename, json &j_main, int level)
{
json j_folder;
j_folder["Level"] = level+1;
j_folder["Name"] = filename.string();
j_folder["Files"] = json::array({});
j_folder["Children"] = json::array({});
for (auto& obj : j_main)
{
if (obj["Level"] == level) {
obj["Children"].push_back(j_folder);
}
}
void DisplayDirectoryTree(const fs::path& pathToShow, int level, json &j_main)
{
if (fs::exists(pathToShow) && fs::is_directory(pathToShow))
{
for (const auto& entry : fs::directory_iterator(pathToShow))
{
auto filename = entry.path().filename();
if (fs::is_directory(entry.status()))
{
DisplayFolderInfo(entry, filename,j_main,level);
level++;
DisplayDirectoryTree(entry,level,j_main);
}
else if (fs::is_regular_file(entry.status()))
DisplayFileInfo(entry, filename,j_main,level);
}
}
}
int main()
{
char folder_path[255];
cout << "Please input name of folder with full path: " << endl;
cin >> folder_path;
json j_main;
j_main["Level"] = 0;
j_main["Children"] = json::array({});
j_main["Files"] = json::array({});
const fs::path pathToShow=folder_path;
DisplayDirectoryTree(pathToShow, 0,j_main);
ofstream o("file.json");
o << setw(4) << j_main << endl;
_getch();
return 0;
}
解决方案
你不需要搜索任何东西,你可以简单地传递子树而不是j_main
.
或者不传递任何东西,逻辑相当简单,适合单个函数:
void DisplayDirectoryTree(const fs::path & pathToShow, json& root, int level = 0)
{
std::vector<json> files, children;
root["Level"] = level;
for (const auto& entry : fs::directory_iterator(pathToShow))
{
json j_entry;
j_entry["Name"] = entry.path().filename().u8string();
if (fs::is_directory(entry.status()))
{
DisplayDirectoryTree(entry.path(), j_entry, level + 1);
children.emplace_back(std::move(j_entry));
}
else
{
j_entry["Size"] = fs::file_size(entry);
j_entry["Path"] = fs::absolute(entry.path()).u8string();
files.emplace_back(std::move(j_entry));
}
}
root["Files"] = files;
root["Children"] = children;
}
int main()
{
std::string folder_path;
cout << "Please input name of folder with full path: " << endl;
cin >> folder_path;
json j_main;
DisplayDirectoryTree(fs::path(folder_path), j_main);
ofstream o("file.json");
o << j_main.dump(4) << endl;
o.close();
return 0;
}
另请注意,您的level++
逻辑是错误的 - 您不需要在循环中增加它,而是传递level + 1
给递归调用。
推荐阅读
- python - 内部函数上的 Python lru_cache 似乎不起作用
- vue.js - 如果 v-for 中带空格的数组的对象名
- php - 为什么这种从邮递员到 Laravel 路线的邮寄方法不起作用?
- sql - Jupyter notebook:使用 %sql 魔法关键字时禁用自动提交
- python - 关于用scrapy抓取论坛的一些问题
- node.js - 为什么管道不适用于各种 NodeJS CLI 工具的 Powershell?
- python - 如何使列表起始端连接?
- python - Python 列出错误的输出
- openmpi - 与已安装软件包中的变体冲突
- apache - Apache 在 MediaWiki 上失败