jsoncpp 接收並解析 http 服務器響應的 json 數據

    接上一篇文章:libcurl 配合 jsoncpp 向 http 服務器發送 post 請求,在上一篇文章中我向 web 服務器使用 post 模擬表單的方式發送了一個請求接收了響應數據。

$./test
*   Trying 192.168.7.6...
* Connected to 192.168.7.6 (192.168.7.6) port 9999 (#0)
> POST /v1/annotation/face-detect HTTP/1.1
Host: 192.168.7.6:9999
User-Agent: Agent
Accept: */*
Content-Length: 95
Content-Type: application/x-www-form-urlencoded

* upload completely sent off: 95 out of 95 bytes
< HTTP/1.1 200 OK
< Server: openresty/1.15.8.2
< Date: Thu, 14 Nov 2019 09:13:50 GMT
< Content-Type: application/json
< Content-Length: 343
< Connection: keep-alive
<
* Connection #0 to host 192.168.7.6 left intact

從 http 的響應頭字段:Content-Type: application/json可知服務器響應了我們一個 json 字符串數據,如下:

{
  "data": [
    {
      "annotation": [
        [
          "c", //類別
          1.0, //confidence
          [    
            256, //x0
            238, //y0
            237, //w
            266  //h
          ]
        ]
      ],
      "file": "/home/kaas/kaas/kaas_server/tests/image/face_detect/_300VW-3D_CatA_114_2141.jpg"
    }
  ],
  "msg": "success",
  "status": 0
}

下面我們使用 jsoncpp 來解析上面這個比較複雜的 json 字符串結構,我在上一篇的代碼中加了一個 parse 函數專門來解析這個 json 串。

#include <iostream>
#include <curl/curl.h>
#include <sstream> //std::stringstream
#include "json/json.h"

/*
處理接收數據處理的回調函數,在這裏我將接收到的數據寫入到數據存放變量(stream)中
*/
static size_t func_write_data(void *ptr, size_t size, size_t nmemb, void *stream) {
    std::string data((const char*) ptr, (size_t) size * nmemb);
    *((std::stringstream*) stream) << data << std::endl;
    return size * nmemb;
}

void parse(const std::string out) {
    Json::Reader jr(Json::Features::strictMode());
    Json::Value jv;
    if (jr.parse(out.c_str(), jv)) {
        int status = jv.get("status",0).asInt();
        std::cout << "status: " << status << std::endl;

        std::string msg = jv.get("msg",0).asString();
        std::cout << "msg: " << msg << std::endl;

        Json::Value data = jv.get("data",0);
        int sz = data.size();
        std::cout << "data length: " << sz << std::endl;
        for (int i=0; i<sz; i++) {
            Json::Value data_i = data[i];
            std::cout << "i: " << i << ", file: " << 
            data_i.get("file",0).asString();

            Json::Value anno = data_i.get("annotation",0);
            int anno_size = anno.size();
            for (int j=0; j<anno_size; j++) {
                std::cout << "name: " << anno[j][0] << std::endl;
                std::cout << "score: " << anno[j][1] << std::endl;
                Json::Value box = anno[j][2];
                int box_size = box.size();
                std::cout << "box_length: " << box_size << std::endl;
                for (int k=0; k<box_size; k++) {
                    std::cout << "box " << k << " :" << box[k] << std::endl;
                }
            }
        }
    }
}

int main(int argc, char* argv[]) {
    /*
    請求參數格式
    {
        'files':[
            "${filepath}"
        ]
    }
    */
    //json 封裝
    std::string path="/home/kaas/kaas/kaas_server/tests/image/face_detect/_300VW-3D_CatA_114_2141.jpg";
    Json::Value files;
    files.append(path);
    std::string request = "files=" + files.toStyledString();

    std::stringstream resp; // 請求響應
    std::string url = "http://192.168.7.6:9999/v1/annotation/face-detect";
    //初始化curl
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
	if (!curl) {
		std::cout << "init curl error" << std::endl;
		return -1;
	}
    //struct curl_slist* header_list = NULL; //need free
    //header_list = curl_slist_append(header_list, "Content-Type:application/x-www-form-urlencoded");
    //curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);

	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3000);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "Agent");

	curl_easy_setopt(curl, CURLOPT_POST, 1); //設置請求方式爲 post
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.c_str()); //加載 post 數據

    //設置接收數據的回調函數以及存放數據的變量
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, func_write_data);

    //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);      //訪選項可以獲取請求詳情
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());  //設置請求 url,必不可少

    CURLcode ret = CURLE_OK;
    ret = curl_easy_perform(curl); //執行請求
    if (CURLE_OK != ret) {
		std::cout << "execute error: " << ret << std::endl;
		return -1;
	}

    //輸出響應結果
    std::cout << resp.str();
    std::cout << "--------------------" << std::endl;
    //解析響應結果
    parse(resp.str());

    curl_easy_cleanup(curl); //釋放資源
    curl_global_cleanup();

    return 0;
}

編譯,運行一下:

[localhost ~]$ cat build.sh
g++ test.cpp -o test -lcurl libjsoncpp.a -Iinclude
[localhost ~]$ ./test
{
  "data": [
    {
      "annotation": [
        [
          "c",
          1.0,
          [
            256,
            238,
            237,
            266
          ]
        ]
      ],
      "file": "/home/kaas/kaas/kaas_server/tests/image/face_detect/_300VW-3D_CatA_114_2141.jpg"
    }
  ],
  "msg": "success",
  "status": 0
}

--------------------
status: 0
msg: success
data length: 1
i: 0, file: /home/kaas/kaas/kaas_server/tests/image/face_detect/_300VW-3D_CatA_114_2141.jpgname: "c"
score: 1
box_length: 4
box 0 :256
box 1 :238
box 2 :237
box 3 :266

ok,就這樣了!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章