提升C++操作Json的开发效率

一、背景

在C++项目开发中,不同的服务之间会定义通讯接口,接口格式定义中的通讯数据往往是json格式的。为了快速开发,我的需求如下:

1.定义好通讯接口后,就定义好了交互的json内容格式。我希望有工具可以一键将json内容转换成C++结构体;

2.服务交互过程中,我希望结构体数据和json内容可以相互转换,并且不需要写两者之间的转换代码。请注意:重点是不需要写两者之间的转换代码

二、解决方案

先说需求2,我在网上找到一个开源库,可以满足此需求,开源库介绍地址:

json与C++结构体互相转换_c++ 结构体转json_xyz347的博客-CSDN博客

gitee地址:xpack: 用于C++结构体和json/xml/bson/mysql的互相转换

简单介绍一下这个库的作用及用法:如下图所示,在结构体中增加XPACK宏定义,就可以轻松完成json字符串与结构体之间相互转换了,节省了大量的编写转换代码的时间。

提升C++操作Json的开发效率_第1张图片

也许有人会说,上图所示的结构体就2个变量,写转换代码几行就搞定了。

如果json的内容如下呢?写转换代码的工作量大不大呢?

{
    "status": 0,
    "message": "message",
    "data": {
        "search_data": [{
                "elements": [{
                        "rating": 0,
                        "name": "奈良市",
                        "url": "/scenic/3/10052/",
                        "wish_to_go_count": 328,
                        "name_orig": "奈良市",
                        "visited_count": 1958,
                        "comments_count": 0,
                        "location": {
                            "lat": 34.685087,
                            "lng": 135.805
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "奈良市",
                        "name_en": "Nara",
                        "type": 3,
                        "id": 10052,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "小樽市",
                        "url": "/scenic/3/26772/",
                        "wish_to_go_count": 266,
                        "name_orig": "小樽市",
                        "visited_count": 954,
                        "comments_count": 0,
                        "location": {
                            "lat": 43.190717,
                            "lng": 140.994662
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "小樽市",
                        "name_en": "Otaru",
                        "type": 3,
                        "id": 26772,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    },
                    {
                        "rating": 0,
                        "name": "挪威",
                        "url": "/scenic/1/3258/",
                        "wish_to_go_count": 788,
                        "name_orig": "挪威",
                        "visited_count": 850,
                        "comments_count": 0,
                        "location": {
                            "lat": 60.472024,
                            "lng": 8.468946
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": 26773,
                        "has_route_maps": false,
                        "rating_users": 0
                    }
                ],
                "type": "destination",
                "title": "国外热门目的地"
            },
            {
                "elements": [{
                        "rating": 0,
                        "name": "台湾",
                        "url": "/scenic/1/3660/",
                        "wish_to_go_count": 37947,
                        "name_orig": "台湾",
                        "visited_count": 15729,
                        "comments_count": 0,
                        "location": {
                            "lat": 23.69781,
                            "lng": 120.960515
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": 45012,
                        "has_route_maps": false,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "香港",
                        "url": "/scenic/1/3814/",
                        "wish_to_go_count": 23495,
                        "name_orig": "香港",
                        "visited_count": 31249,
                        "comments_count": 0,
                        "location": {
                            "lat": 22.396428,
                            "lng": 114.109497
                        },
                        "has_experience": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/country.png",
                        "type": 1,
                        "id": 55012,
                        "has_route_maps": true,
                        "rating_users": 0
                    },
                    {
                        "rating": 0,
                        "name": "厦门",
                        "url": "/scenic/3/65012/",
                        "wish_to_go_count": 29887,
                        "name_orig": "厦门",
                        "visited_count": 26077,
                        "comments_count": 0,
                        "location": {
                            "lat": 24.477188,
                            "lng": 118.094398
                        },
                        "has_experience": false,
                        "rating_users": 0,
                        "name_zh": "厦门",
                        "name_en": "Xiamen",
                        "type": 3,
                        "id": 65012,
                        "has_route_maps": false,
                        "icon": "http://media.breadtrip.com/images/icons/2/city.png"
                    }
                ],
                "type": "destination",
                "title": "国内热门目的地"
            }
        ],
        "date_time": "2017-09-11 10:52:27.811321",
        "elements": [{
                "type": 1,
                "data": [{
                        "platform": "android",
                        "image_url": "http://photos.breadtrip.com/covers_2017_09_05_d5b225291045767fcfa0508f3d96ae26.jpg?imageView/2/w/960/",
                        "html_url": "http://www.iqiyi.com/v_19rr8w7drg.html?dummy=&wx_uid2=wxidoG0a9jsIGfq1jln1HtWebMCOKKSQ"
                    },
                    {
                        "platform": "android",
                        "image_url": "http://photos.breadtrip.com/covers_2014_12_25_ed43331bac65ee0752f7e56116993b2c.jpg?imageView2/2/w/750/format/jpg/interlace/1/",
                        "html_url": "http://web.breadtrip.com/mobile/destination/topic/2387718817/"
                    },
                    {
                        "platform": "android",
                        "image_url": "http://photos.breadtrip.com/covers_2014_10_29_46217a91ace672787ed1fec4c2011b52.png?imageView2/2/w/750/format/jpg/interlace/1/",
                        "html_url": "http://web.breadtrip.com/mobile/destination/topic/2387718790/"
                    }

                ],
                "desc": "广告banner"
            },
            {
                "type": 11,
                "data": [{
                    "title": "每日精选故事"
                }],
                "desc": ""
            }

        ]
    }
}

 使用xpack开源库之后,只需要如下定义结构体即可,转换代码不需要你写!!

struct Location {
    int lat;
    int lng;
    XPACK(O(lat, lng)); // 添加宏定义XPACK在结构体定义结尾
};

struct Elements2 {
    int comments_count;
    bool has_experience;
    bool has_route_maps;
    std::string icon;
    int id;
    Location location;
    std::string name;
    std::string name_en;
    std::string name_orig;
    std::string name_zh;
    int rating;
    int rating_users;
    int type;
    std::string url;
    int visited_count;
    int wish_to_go_count;
    XPACK(O(comments_count, has_experience, has_route_maps, icon, id, location, name, name_en, name_orig, name_zh, rating, rating_users, type, url, visited_count, wish_to_go_count)); // 添加宏定义XPACK在结构体定义结尾
};

struct Search_data {
    std::vector elements;
    std::string title;
    std::string type;
    XPACK(O(elements, title, type)); // 添加宏定义XPACK在结构体定义结尾
};

struct Data2 {
    std::string html_url;
    std::string image_url;
    std::string platform;
    XPACK(O(html_url, image_url, platform)); // 添加宏定义XPACK在结构体定义结尾
};

struct Elements {
    std::vector data;
    std::string desc;
    int type;
    XPACK(O(data, desc, type)); // 添加宏定义XPACK在结构体定义结尾
};

struct Data {
    std::string date_time;
    std::vector elements;
    std::vector search_data;
    XPACK(O(date_time, elements, search_data)); // 添加宏定义XPACK在结构体定义结尾
};

struct Ticket {
    Data data;
    std::string message;
    int status;
    XPACK(O(data, message, status)); // 添加宏定义XPACK在结构体定义结尾
};

到此为止,我的需求2已经完美解决了。再说需求1,请看上面那段复杂的json示例,要根据这个json格式定义结构体,工作量大不大?有没有工具可以将上面的json转换成结构体定义?我在网上找了很久,找到一个勉强能用的,网址是:Instantly parse JSON in any language | quicktype

转换效果如下:

提升C++操作Json的开发效率_第2张图片

这个在线网站转换出来的结构体定义,我还需要手动添加XPACK宏才能配合xpack开源库

使用。为了追求极致的开发效率,我使用Qt5手撸了一个转换工具,工具使用效果如下:

提升C++操作Json的开发效率_第3张图片

 如上图所示,只需要将json内容复制到工具的左侧输入框,然后点“生成”按钮,即可自动将结构体生成出来。

该转换工具的下载地址:https://download.csdn.net/download/liuguangzhou123/88053077

至此,我的需求已完美解决!

你可能感兴趣的:(C/C++,json,c++,json与结构体相互转换)