CppBind is a C++ header-only library that allow mapping JSON/CSV values to/from C++ Class object. It's not a json/csv parser, it use JsonCPP as low level parser. This project is inspried by Java Jackson.
CppBind documentation is generated using Doxygen.
Just download and compile your project with cppbind;
git clone https://github.com/trumanz/cppbind
g++ -I path/to/cppbind example.cpp -o example
- Data-binding C++ Class Object to and from JSON/CSV. Not oly
- Type of a Class member variable could be primitive type, other Class type or C++ standard container template(vector, list, map, set).
- Class memeber variable could be optional, predefined default value.
- Foreigner table support.
- Dynamic type decode support.
- User defined serialization and deserialization behavior.
I feel boring work when I am working on a C++ project which have plenty of configuration write by Json. I saw Java Jackson could easily mapping Json and Object, but C++ can not do that since it do not have reflection mechanism, But C++ have template which let compiler auto generate useful codes by variable type.
There is an simple example to show how cppbind simplfy codes. Here is the conclusion at beginning,
CppBind | Bare JsonCpp | |
---|---|---|
Coding works | 5 lines | 40 lines |
Let's consider parse below JSON data to be A C++ Class Object. JSON Data
{
"name" : "Bruce"
"bornDate" : "2020-01-01",
"skillsScore" : {
"football" : 8,
"music" : 7
}
}
With CppBind
class Person {
public:
std::string name;
boost::gregorian::date born_date;
boost::shared_ptr< std::map<std::string, int> > optional_skills_score;
void setBind(Binder *binder, bool load){
binder->bind("name", name);
binder->bind("bornDate", born_date);
binder->bind("skillsScore", optional_skills_score);
}
};
Person* parsePerson(std::istream &json_input){
return JsonDecoder().decode<Student>(json_str);
}
Bare JsonCpp
class Person {
public:
std::string name;
boost::gregorian::date born_date;
boost::shared_ptr< std::map<std::string, int> > optional_skills_score;
}
Person* parsePerson(std::istream &json_input)
{
Json::Value root;
Json::Reader reader;
bool parsingSuccessful = reader.parse(json_input, root);
Person *p = new Person();
//parse name
Json::Value jv_name = root["name"];
if (!jv_name.isNull()) {
p->name = jv_name.asString()
} else {
delete p;
return NULL;
}
//parse born date, this code missing data pattern check
Json::Value jv_born_date = root["bornDate"]
if (!jv_name.isNull()) {
std::istringstream ss(jv_name.asString());
boost::gregorian::date d;
ss >> d;
p->born_date.reset(new boost::gregorian::date(d));
}
//parse optonal skill score map
Json::Value jv_skill_score = root["skillsScore"]
if (!skill_score.isNull()) {
if (!jv_skill_score.isObject()) {
delete p;
return NULL;
}
p->optional_skills_score.reset(new std::map<std::string, int>());
Json::Value::Members keys = jv_skill_score.getMemberNames();
for (Json::Value::Members::iterator it = keys.begin();
it != keys.end(); it++) {
std::string key_str = *it;
Json::Value jv_value = jv_skill_score[*it];
int score = jv_value.asInt();
p->optional_skills_score->insert({ key_str, score });
}
}
return p;
}
示例代码
示例代码
setBind函数:自定义类Student,并实现成员函数setBind, 函数实现为为调用binder->bind将json node名称值与成员变量建立联系;
JsonDecoder().decode模板函数:解码一个json string为一个C++类对象。
JsonDecoder().encodeToStr模板函数:编码一个C++类对象为一个json string。
binder默认支持绑定的基本类型:
说明 | |
---|---|
bool | |
int32_t | |
uint32_t | |
int64_t | |
uint64_t | |
float | |
double | |
std::string | |
Json::Value | |
boost::posix_time::ptime | 默认格式"YYYY-mm-dd HH:MM:SS" |
boost::gregorian::date | 默认格式"YYYY-mm-dd" |
boost::posix_time::time_duration | 默认格式"HH:MM:SS” |
binder支持的C++模板类型
说明 | |
---|---|
std::vector | 元素可为对象或对象指针, 映射为json array |
std::list | 元素可为对象或对象指针, 映射为json array |
std::set | 元素可为对象或对象指针, 映射为json array |
std::map | key值为string类型,元素可为对象或对象指针,映射为json object |
模板对象之间可相互嵌套,如下
class MyObj{
std::map<std::string, std::vector<Student> > group_students;
std::set<std::set<Student> > group_students_v2;
void setBind(Binder *binder, bool load){
binder->bind("group_students", group_students);
binder->bind("group_students_v2", group_students_v2);
}
}
参考 StringConverterManager str_convert_mgmt;
可以通过向 binder中注册外部类型的Converter实现;默认支持的对外部boost::posix_time::ptime, boost::gregorian::date, boost::posix_time::time_duration即通过此方式
refer devops/build-ubuntu-vcpkg.yml
CI refered by https://github.com/microsoft/cpprestsdk/blob/master/azure-pipelines.yml