昨天寫了《Boost學習之讀寫ini文件》,發現boost不止可以讀寫ini文件,還可以很方便的讀寫json文件。之前在C++中讀寫json比較抽象,從boost的語法可以很輕鬆的看出來。與讀寫ini一樣,json格式,在boost中也被抽象爲property_tree。
Boost中Json數據類型
在構建json文件時,我們只需要構建多個tree節點,按照對應的樹形結構組合在一起即可。從boost寫json文件API源碼可以看出,property_tree支持三種類型,分別是value 、array, object。
- value:系統默認數據類型;
- array:數組類型,可以嵌套自定義類型,在方括號中存放。
- object:使用者自定義的數據類型,在花括號中存放。
Boost寫Json核心源碼
以下代碼段,是boost寫入json核心代碼。
template<class Ptree>
void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
const Ptree &pt,
int indent, bool pretty)
{
typedef typename Ptree::key_type::value_type Ch;
typedef typename std::basic_string<Ch> Str;
// Value or object or array
if (indent > 0 && pt.empty())
{
// Write value
Str data = create_escapes(pt.template get_value<Str>());
stream << Ch('"') << data << Ch('"');
}
else if (indent > 0 && pt.count(Str()) == pt.size())
{
// Write array
stream << Ch('[');
if (pretty) stream << Ch('\n');
typename Ptree::const_iterator it = pt.begin();
for (; it != pt.end(); ++it)
{
if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
write_json_helper(stream, it->second, indent + 1, pretty);
if (boost::next(it) != pt.end())
stream << Ch(',');
if (pretty) stream << Ch('\n');
}
if (pretty) stream << Str(4 * indent, Ch(' '));
stream << Ch(']');
}
else
{
// Write object
stream << Ch('{');
if (pretty) stream << Ch('\n');
typename Ptree::const_iterator it = pt.begin();
for (; it != pt.end(); ++it)
{
if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':');
if (pretty) stream << Ch(' ');
write_json_helper(stream, it->second, indent + 1, pretty);
if (boost::next(it) != pt.end())
stream << Ch(',');
if (pretty) stream << Ch('\n');
}
if (pretty) stream << Str(4 * indent, Ch(' '));
stream << Ch('}');
}
}
簡單的Json示例
構造簡單Json示例
看完源碼,下面將按照三種不同類型構造一個簡單地json文件
void build_json()
{
ptree root; // 根節點
ptree arr;
root.put("version", 1); // value類型,一級節點
// 二級節點
ptree node1, node2, node3, node4, node5;
node1.put("frame_rate", 0);
node1.put("bit_rate", 1);
node1.put("resolution", 3);
node1.put("boot", 0);
node1.put("ssfs", 2);
// 添加二級節點
root.add_child("0", node1);
root.add_child("1", node1);
root.add_child("2", node1);
stringstream s;
write_json(s, root, false);
string out = s.str();
ofstream oftream("config_json.json", std::ios_base::out);
oftream << out;
oftream.close();
}
運行結果
{
"version": "1",
"0": {
"frame_rate": "0",
"bit_rate": "1",
"resolution": "3",
"boot": "0",
"ssfs": "2"
},
"1": {
"frame_rate": "0",
"bit_rate": "1",
"resolution": "3",
"boot": "0",
"ssfs": "2"
},
"2": {
"frame_rate": "0",
"bit_rate": "1",
"resolution": "3",
"boot": "0",
"ssfs": "2"
}
}
簡單Json解析示例
一般有寫入就有讀取,下面示例代碼,將結合上述json結構,讀取相關信息,並打印
void Read_json()
{
ifstream ifstrema("config_json.json", std::ios_base::in);
ptree node; //初始化根節點
read_json(ifstrema, node); // 將json文件讀入根節點
int intVersion = node.get<int>("version"); // 獲取一級節點“version”的值
ptree temp = node.get_child("0"); // 獲取一級節點“0”的子節點信息
// 迭代一級節點的子節點中的每個項
for (boost::property_tree::ptree::iterator it = temp.begin(); it != temp.end(); ++it)
{
cout << "first:" << it->first << endl; // key
cout << "second:" << it->second.data() << endl; // value
}
}
運行結果
可以看出,json是按照鍵值對存儲,讀取時,通過鍵獲取相對應的值。
較複雜的Json示例
構造較複雜的Json
void build_json()
{
ptree root, node1, object;
ptree arr;
ptree arrv1, arrv2, arrv3;
// value 類型
root.put("version", 1);
bool boolvalue = true;
root.put("boolean", boolvalue);
root.put("null", "null");
root.put("tip", "Hello World");
node1.put("frame_rate", 0);
node1.put("bit_rate", 1);
node1.put("resolution", 3);
node1.put("boot", 0);
node1.put("ssfs", 2);
root.add_child("0", node1);
root.add_child("10", node1);
root.add_child("20", node1);
// arry類型
arrv1.put("a", "b");
arrv2.put("Tom", "23");
arrv3.put("Tony", "4");
arrv1.put("marble", "2222");
arr.push_back(std::make_pair("", arrv1));
arr.push_back(std::make_pair("", arrv2));
arr.push_back(std::make_pair("", arrv3));
// object類型
object.put("a", "b");
object.put("c", "d");
object.put("e", "f");
root.add_child("1", arr);
root.add_child("2", arr);
root.add_child("object", object);
stringstream s;
write_json(s, root, false);
string out = s.str();
ofstream oftream("config_json.json", std::ios_base::out);
oftream << out;
oftream.close();
cout << out;
}
執行結果
{
"version": "1",
"boolean": "true",
"null": "null",
"tip": "Hello World",
"0": {
"frame_rate": "0",
"bit_rate": "1",
"resolution": "3",
"boot": "0",
"ssfs": "2"
},
"10": {
"frame_rate": "0",
"bit_rate": "1",
"resolution": "3",
"boot": "0",
"ssfs": "2"
},
"20": {
"frame_rate": "0",
"bit_rate": "1",
"resolution": "3",
"boot": "0",
"ssfs": "2"
},
"1": [{
"a": "b",
"marble": "2222"
}, {
"Tom": "23"
}, {
"Tony": "4"
}],
"2": [{
"a": "b",
"marble": "2222"
}, {
"Tom": "23"
}, {
"Tony": "4"
}],
"object": {
"a": "b",
"c": "d",
"e": "f"
}
}
較複雜的Json讀取
void Read_json()
{
ifstream ifstrema("config_json.json", std::ios_base::in);
ptree node;
read_json(ifstrema, node);
int intVersion = node.get<int>("version");
// 迭代獲取對象
ptree temp = node.get_child("0");
for (boost::property_tree::ptree::iterator it = temp.begin(); it != temp.end(); ++it)
{
cout << "first:" << it->first << endl;
cout << "second:" << it->second.data() << endl;
}
ptree objNode = node.get_child("object");
for (boost::property_tree::ptree::iterator it = objNode.begin(); it != objNode.end(); ++it)
{
cout << "object fist: " << it->first << endl;
cout << "object second: " << it->second.data() << endl;
}
// 獲取數組對象,先獲取迭代器首地址,然後按照鍵值對獲取值
ptree arr = node.get_child("1");
boost::property_tree::ptree::iterator it = arr.begin();
cout << it->second.get<string>("a") << endl;
cout << it->second.get<string>("marble") << endl;
it++; // 迭代器++,指針指向下一個數組首地址。
cout << it->second.get<string>("Tom") << endl;
it++;
}
運行結果
寫在結尾
以上是boost讀取json文件的步驟和注意點,剛接觸boost,較多的語法知識等還在熟悉中,如果本文中有錯誤,請隨時聯繫博主進行修改;如果對你有幫助,請點贊支持,謝謝。