提示:C++应用开发中读写配置文件必不可少,本文简洁讲述jsoncpp交叉编译,并通过封装Wrapper优雅的从json文件读取数据
目录
前言
应用开发中读写配置文件必不可少,Jsoncpp是很优秀的一个读取json文件工具,本文简洁讲述jsoncpp交叉编译,并通过封装Wrapper优雅的从json文件读取数据。
一、jsoncpp是什么
jsoncpp 是一个 C++ 库,用于解析和生成 JSON 数据。它提供了简单易用的 API,使得在 C++ 程序中处理 JSON 数据变得非常方便。jsoncpp 支持现代 C++ 特性,并且经过了良好的测试,是一个成熟稳定的 JSON 处理库。
二、交叉编译
2.1 下载源代码
可以直接从github拉取
git clone https://github.com/open-source-parsers/jsoncpp.git
若你不想用最新版本的jsoncpp,可以点击这里下载你需要的版本的source_code
2.2 交叉编译
交叉编译前需要确保你已安装了交叉编译器,以本人项目的arm-v01c02-linux-musleabi-g++编译器为例执行如下代码
# 进入源码目录
cd jsoncpp
mkdir build
cd build
# 将下面的CMAKE_CXX_COMPILER 替换为你自己的交叉编译器
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_CXX_COMPILER=arm-v01c02-linux-musleabi-g++ -DJSONCPP_WITH_TESTS=OFF ..
make -j8
make install
cd -
运行完成后你会在jsoncpp的install目录下看到如下文件,说明编译完成
(base) xxx@server:~/third_party/jsoncpp/install$ tree . -L 2
.
├── include
│ └── json
└── lib
├── cmake
├── libjsoncpp.a
├── libjsoncpp.so -> libjsoncpp.so.27
├── libjsoncpp.so.1.9.7
├── libjsoncpp.so.27 -> libjsoncpp.so.1.9.7
├── objects-Release
└── pkgconfig
三、读取json文件
3.1 封装json_wrapper
创建json_wrapper.h文件 代码如下(示例):
#ifndef INCLUDE_COMMON_JSON_WRAPPER_H_
#define INCLUDE_COMMON_JSON_WRAPPER_H_
#include <string.h>
#include <memory>
#include <string>
#include <vector>
#include "json/json.h"
class JsonConfigWrapper {
public:
explicit JsonConfigWrapper(Json::Value config) : config_(config) {}
int GetIntValue(std::string key, int default_value = 0) {
auto value_js = config_[key.c_str()];
if (value_js.isNull()) {
return default_value;
}
return value_js.asInt();
}
bool GetBoolValue(std::string key, bool default_value = false) {
auto value_int = GetIntValue(key, default_value);
return value_int == 0 ? false : true;
}
float GetFloatValue(std::string key, float default_value = 0.0) {
auto value_js = config_[key.c_str()];
if (value_js.isNull()) {
return default_value;
}
return value_js.asFloat();
}
std::string GetSTDStringValue(std::string key, std::string default_value = "") {
auto value_js = config_[key.c_str()];
if (value_js.isNull()) {
return default_value;
}
return value_js.asString();
}
std::vector<std::string> GetSTDStringArray(std::string key) {
auto value_js = config_[key.c_str()];
std::vector<std::string> ret;
if (value_js.isNull()) {
return ret;
}
ret.resize(value_js.size());
for (Json::ArrayIndex i = 0; i < value_js.size(); ++i) {
ret[i] = value_js[i].asString();
}
return ret;
}
std::vector<int> GetIntArray(std::string key) {
auto value_js = config_[key.c_str()];
std::vector<int> ret;
if (value_js.isNull()) {
return ret;
}
ret.resize(value_js.size());
for (Json::ArrayIndex i = 0; i < value_js.size(); ++i) {
ret[i] = value_js[i].asInt();
}
return ret;
}
std::vector<int> GetIntArray(int key) {
auto value_js = config_[key];
std::vector<int> ret;
if (value_js.isNull()) {
return ret;
}
ret.resize(value_js.size());
for (Json::ArrayIndex i = 0; i < value_js.size(); ++i) {
ret[i] = value_js[i].asInt();
}
return ret;
}
std::shared_ptr<JsonConfigWrapper> GetSubConfig(std::string key) {
auto value_js = config_[key.c_str()];
if (value_js.isNull()) {
return nullptr;
}
return std::shared_ptr<JsonConfigWrapper>(new JsonConfigWrapper(value_js));
}
std::shared_ptr<JsonConfigWrapper> GetSubConfig(int key) {
auto value_js = config_[key];
if (value_js.isNull()) {
return nullptr;
}
return std::shared_ptr<JsonConfigWrapper>(new JsonConfigWrapper(value_js));
}
bool HasMember(std::string key) { return config_.isMember(key); }
int ItemCount(void) { return config_.size(); }
protected:
Json::Value config_;
};
#endif // INCLUDE_COMMON_JSON_WRAPPER_H_
3.2读取json文件
我们创建一个sample.json文件内容如下
{ "input_size": [1, 1, 33, 512],
"output_size": [1, 33, 88],
"input_names": ["input"],
"output_names":["output_0", "output_1", "output_2", "output_3"],
"model_path": "models/model.encypted",
"region": "center"
}
在main.cpp中我们用封装的指针封装Json::Value,通过get方法就可以方便的从文件中读取字符,字符串数组和Int数组等
#include "json_wrapper.h"
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <memory>
int main() {
std::string file_path = "sample.json";
std::ifstream ifs(file_path);
if (!ifs.is_open()) {
std::cerr << "Failed to open file: " << file_path << std::endl;
return 1;
}
Json::Value cfg_jv;
ifs >> cfg_jv;
JsonConfigWrapper *config = new JsonConfigWrapper(cfg_jv);
std::vector<std::string> str_array = config->GetSTDStringArray("output_names");
for (auto& str : str_array) {
std::cout << str << std::endl;
}
delete config;
ifs.close();
return 0;
}
编译执行上面的文件我们可以看到如下输出,说明代码运行良好
/workspace/install/ # ./test_jsoncpp
output_0
output_1
output_2
output_3
总结
本文介绍了C++应用中读写JSON配置文件的方法,重点讲解了jsoncpp库的交叉编译过程。主要内容包括:1) jsoncpp库的特性与优势;2) ARM平台的交叉编译步骤;3) 封装JsonConfigWrapper类实现便捷的JSON数据读取方法;4) 通过示例展示了如何读取JSON文件中的字符串数组等数据类型。该方案为C++项目提供了一种高效、优雅的JSON配置处理方式,适用于嵌入式开发等需要交叉编译的场景。