1 JSON文件简介[1]

一个项目在设计时会存在很多参数,比如data文件路径、外设名称与相关参数、文件储存路径等等,这些参数根据实际需要可能需要修改的频率比较频繁,如果放在程序里面不仅查找比较麻烦,而且每次修改完就得重新编译一次,超级麻烦。所以可以将这种类型的参数文件都放在一个文本里面,然后设计一个函数接口来读取这些参数并存储在结构体或者其它类型的容器中。

之前为了方便将参数写进了TXT中,key和value之间通过=进行连接,以方便查找。最近接触了另外一种存储外参的文件格式JSON文件,JSON文件有自己的文件规则,并且boost库提供了解析json文件的接口。

1.1 JSON文件的语法规则

  1. 每一条数据通过key:value的形式储存,如"name":"lsx"
  2. 数据之间通过逗号分隔,如"name":"lsx","age":16
  3. 花括号用于保存对象,如"info":{"name":"lsx","age":16}
  4. 中括号用于保存数组,如"info":["name":"lsx","age":16]
  5. 一个数组中可以包含多个对象,一个对象中也可以包含多个数组

1.2 JSON值的类型

  1. 数字(整型或浮点型表示)
  2. 字符串(在双引号中)
  3. 逻辑值(true/false)
  4. 对象(在花括号中)
  5. 数组(在中括号中)

2 JSON文件解析

1.创建ptree对象

boost::property_tree::ptree json_root;

2.读取file文件,并将根节点存储赋值给json_root

boost::property_tree::read_json<boost::property_tree::ptree>(file_name, json_root);

3.获取某个子节点信息
对于某个对象或者数组,可以嵌套更多的普通键值对,对象和数组,
把一个对象或者数组对应的结构成为一个子节点,
如果在该子节点下还存在子节点,则继续获取子节点,
直到是基本的组成元素

//这里只列举两层
boost::property_tree::ptree elements = json_root.get_child("xxx");
boost::property_tree::ptree sub_elements = json_root.get_child("xxx");

4.对于结构规则的子节点信息进行遍历
对于下面所举例的数组和对象,有一个共同特点就是他们包含的信息都具有相似的结构,而且组成每个结构的key的名称均相同,这样就可以通过遍历的方式获得每个节点中的元素

{
    "m1":[123],
    "m2":[[1,2,3],[4,5,6]],
    "m3":[
        {
            "key1":"value1",
            "key2":"value2" 
        },
        {
            "key1":"value3",
            "key2":"value4" 
        }
    ],
    "obj":{
        {
            "key3":"value5",
            "key4":"value6"
        },
        {
            "key3":"value7",
            "key4":"value8"
        },
    }
}

基于迭代器进行遍历

//创建一个迭代器
boost::property_tree::ptree::iterator json_iterator;
//基于迭代器进行循环遍历
for(json_iterator=elements.begin();json_iterator!=elements.end();json_iterator++)
{
    string key1 = json_iterator->second.get<string>("key1");
    string key2 = json_iterator->second.get<string>("key2");
}

通过C++11提供的方式遍历
其中迭代器的类型为boost::property_tree::ptree::value_type*
value_type的结构为std::pair<const Key,self_type>
这样还可以通过C++11提供的方式遍历节点中的内容

for(auto value : elements)
{
    string key1 = value.second.get<string>("key1");
    string key2 = value.second.get<string>("key2");    
}

示例代码

#include<iostream>
#include<string>
#include<vector>
#include <boost/property_tree/ptree.hpp>  
#include <boost/property_tree/json_parser.hpp>  

using namespace std;

namespace pt = boost::property_tree;

//解析普通数组
template <class T>
bool getArrayDataFromJson(std::vector<T> &vecData, pt::ptree & nodeJSON, string path) {
    //1.循环遍历数组中所有的子节点(数组中的每一个元素)
	for (pt::ptree::value_type &value : nodeJSON.get_child(path))
	{
        //2.获得每一个子节点的值,并将其放进vector
		T tValue =value.second.get_value<T>();
		vecData.push_back(tValue);
	}
	return true;
}



int main()
{
    string file_name = "./test.json";

    // 创建ptree对象
    pt::ptree json_root;
    // 读取file文件,并将根节点存储赋值给json_root
    pt::read_json<pt::ptree>(file_name, json_root);
    
    //解析普通键值对
    string g_version = json_root.get<string>("version");
    string g_description = json_root.get<string>("description");
    int g_test_number =  json_root.get<int>("test_number");
    string g_end_desc = json_root.get<string>("end_desc");

    cout<<"version="<<g_version<<endl;
    cout<<"description="<<g_description<<endl;
    cout<<"test_number="<<g_test_number<<endl;
    cout<<"end_desc="<<g_description<<endl;

    //解析普通数组
    vector<int> gv_location1,gv_location2;
    bool flag_gv_location1 = getArrayDataFromJson(gv_location1, json_root, "location1");
    bool flag_gv_location2 = getArrayDataFromJson(gv_location2, json_root, "location2");

    cout<<"gv_location1="<<endl;
    for(auto v:gv_location1)cout<<v<<" "<<endl;
    cout<<"gv_location2="<<endl;
    for(auto v:gv_location2)cout<<v<<" "<<endl;

    //解析数组中包含对象
    //1.通过循环迭代获取test_choice数组的所有子节点中的对象
    for (pt::ptree::value_type &elements_test_choice : json_root.get_child("test_choice"))
    {
        //2.再通过解析普通键值对的方式获得对象中的每个值
        string key_name = elements_test_choice.second.get<std::string>("name");
        bool value_enable = elements_test_choice.second.get<bool>("enable");
        cout<<"key_name="<<key_name<<"\tvalue_enable="<<value_enable<<endl;
    }

    //对象中仅包含键值对
    //1.获取该对象对应的子节点
    pt::ptree element_path = json_root.get_child("path_set");
    //2.获取该对象中每个元素(键值对)
    string g_load_path = element_path.get<string>("load_path");
    string g_save_path = element_path.get<string>("save_path");

    cout<<"g_load_path="<<g_load_path<<endl;
    cout<<"g_save_path="<<g_save_path<<endl;

    //对象中仅包含数组
    vector<int>gv_t1,gv_t2;
    //1.获取该对象对应的子节点
    pt::ptree element_t_matrix = json_root.get_child("T_Matrix");
    bool gv_t1_flag = getArrayDataFromJson(gv_t1,element_t_matrix,"t1"); 
    bool gv_t2_flag = getArrayDataFromJson(gv_t2,element_t_matrix,"t2");

    cout<<"gv_t1=[";
    for(auto v:gv_t1)cout<<v<<" ";
    cout<<"]"<<endl;
    cout<<"gv_t2=[";
    for(auto v:gv_t2)cout<<v<<" ";
    cout<<"]"<<endl;

    //对象中包含对象
    //1.获得该对象的子节点对象
    pt::ptree ele_other = json_root.get_child("other_info");

    //1.通过C++11方式进行遍历
    for(auto sub_value :ele_other)
    {
        //对每个子节点对象(即sub_value.second)进行解析
        string sub_info_temp = sub_value.second.get<string>("info");
        vector<int> sub_v_temp;
        bool sub_v_temp_flag = getArrayDataFromJson(sub_v_temp,sub_value.second,"Matrix");
        cout<<sub_info_temp<<"=[";
        for(auto v:sub_v_temp)cout<<v<<" ";
        cout<<"]"<<endl;
    }
    //2.通过迭代器进行遍历
    pt::ptree::iterator it;
    for(it = ele_other.begin();it!=ele_other.end();it++)
    {
        //对每个子节点对象(即sub_value.second)进行解析
        string sub_info_temp = it->second.get<string>("info");
        vector<int> sub_v_temp;
        bool sub_v_temp_flag = getArrayDataFromJson(sub_v_temp,it->second,"Matrix");
        cout<<sub_info_temp<<"=[";
        for(auto v:sub_v_temp)cout<<v<<" ";
        cout<<"]"<<endl;
    }

    //对象中包含普通键值对.数组和对象
    //1.获取对象子节点信息
    pt::ptree element_color_cam = json_root.get_child("camera_device");
    //1.1获取对象中普通键值对
    string ele_name = element_color_cam.get<string>("name");
    string ele_path = element_color_cam.get<string>("path");
    cout<<ele_name<<"\t"<<ele_path<<endl;

    //1.2获取对象中数组
    vector<int> gv_fov,gv_res;
    bool gv_fov_flag = getArrayDataFromJson(gv_fov,element_color_cam,"FOV");
    bool gv_res_flag = getArrayDataFromJson(gv_res,element_color_cam,"RES");
    cout<<"fov=[";
    for(auto v:gv_fov)cout<<v<<" ";
    cout<<"]"<<endl;
    cout<<"res=[";
    for(auto v:gv_res)cout<<v<<" ";
    cout<<"]"<<endl;

    //1.3获取对象中的对象的子节点信息
    pt::ptree sub_Intrinsic = element_color_cam.get_child("Intrinsic");
    cout<<"fx="<<sub_Intrinsic.get<float>("fx")<<endl;
    cout<<"fy="<<sub_Intrinsic.get<float>("fy")<<endl;
    cout<<"cx="<<sub_Intrinsic.get<float>("cx")<<endl;
    cout<<"cy="<<sub_Intrinsic.get<float>("cy")<<endl;

    return 0;
}

json文件

{
    "version":"test_json v1.0",
    "description":"this demo used to practice json analysis",
    "test_number":78322,
    "path_set":{
        "load_path":"./data",
        "save_path":"./result"
    },
    "camera_device":{
        "name":"cam1",
        "path":"/sys/dev/",
        "FOV":[30,50],
        "RES":[640,480],
        "Intrinsic":{
            "fx":50.2155,
            "fy":45.1245,
            "cx":0.55454,
            "cy":0.55488
        }
    },
    "T_Matrix":{
        "t1":[1,2,3],
        "t2":[4,5,6]
    },
    "other_info":{
        "info_1":{
            "info":"hello world",
            "Matrix":[21,21,21,21]
        },
        "info_2":{
            "info":"hello C++",
            "Matrix":[22,22,22,22]
        }
    },
    "location1":[23,23,2333],
    "location2":[233,233,23333],
    "test_choice":[
        {
            "name":"test1",
            "enable":true
        },
        {
            "name":"test2",
            "enable":false
        },
        {
            "name":"test1",
            "enable":true
        }
    ],
    "end_desc":"thank you"
}

[1]https://blog.csdn.net/jinzhu1911/article/details/100050852?spm=1001.2014.3001.5506

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐