Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中使用curl并解析JSON响应_C_Parsing_Curl_Json C - Fatal编程技术网

如何在C中使用curl并解析JSON响应

如何在C中使用curl并解析JSON响应,c,parsing,curl,json-c,C,Parsing,Curl,Json C,下面的代码编译并打印响应 我的问题是:作为表示对象的字符串的响应,如何将res转换为字符串或直接转换为JSON对象 #include <stdio.h> #include <curl/curl.h> #include <json-c/json.h> int main(int argc, char **argv) { CURL *curl; CURLcode res; curl = curl_easy_init(); if(c

下面的代码编译并打印响应

我的问题是:作为表示对象的字符串的响应,如何将res转换为字符串或直接转换为JSON对象

#include <stdio.h>
#include <curl/curl.h>
#include <json-c/json.h>

int main(int argc, char **argv) {
    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();

    if(curl) {
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:8080/system/genpass");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "length: 20");
        headers = curl_slist_append(headers, "numbers: true");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        res = curl_easy_perform(curl);
        printf("%u",res);
    }

    curl_easy_cleanup(curl);
}

不能简单地将函数的返回码转换为字符串。 他们没有任何关系

相反,您需要直接处理接收到的数据。 为此,您需要注册一个能够处理数据的回调函数。 这是在中描述的

例如:

typedef struct {
    unsigned char *buffer;
    size_t len;
    size_t buflen;
} get_request;

#define CHUNK_SIZE 2048

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    size_t realsize = size * nmemb; 
    get_request *req = (get_request *) userdata;

    printf("receive chunk of %zu bytes\n", realsize);

    while (req->buflen < req->len + realsize + 1)
    {
        req->buffer = realloc(req->buffer, req->buflen + CHUNK_SIZE);
        req->buflen += CHUNK_SIZE;
    }
    memcpy(&req->buffer[req->len], ptr, realsize);
    req->len += realsize;
    req->buffer[req->len] = 0;

    return realsize;
}


int main(int argc, char **argv) {
    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();

    get_request req = {.buffer = NULL, .len = 0, .buflen = 0};

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "length: 20");
        headers = curl_slist_append(headers, "numbers: true");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        req.buffer = malloc(CHUNK_SIZE);
        req.buflen = CHUNK_SIZE;

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&req);

        res = curl_easy_perform(curl);
        printf("Result = %u\n",res);

        printf("Total received bytes: %zu\n", req.len);
        printf("Received data:/n%s\n", req.buffer);
        free(req.buffer);        
    }

    curl_easy_cleanup(curl);
}
输出:

receive chunk of 1256 bytes
Result = 0
Total received bytes: 1256
Received data:
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
GET请求完成后,您可以访问req->buffer中的数据,并解析JSON对象或任何其他数据。 需要添加realloc等的错误检查

我使用了一种方法,能够处理接收到的任何数量的块中的任何长度的内容。 如果您知道预期内容的长度,可以使用固定大小的缓冲区


正如您在我的示例中所看到的,用户数据结构在下载完成后仍然存在,内容可以在curl\u easy\u perform returns之后派生。

您不能简单地将函数的返回代码转换为字符串。 他们没有任何关系

相反,您需要直接处理接收到的数据。 为此,您需要注册一个能够处理数据的回调函数。 这是在中描述的

例如:

typedef struct {
    unsigned char *buffer;
    size_t len;
    size_t buflen;
} get_request;

#define CHUNK_SIZE 2048

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    size_t realsize = size * nmemb; 
    get_request *req = (get_request *) userdata;

    printf("receive chunk of %zu bytes\n", realsize);

    while (req->buflen < req->len + realsize + 1)
    {
        req->buffer = realloc(req->buffer, req->buflen + CHUNK_SIZE);
        req->buflen += CHUNK_SIZE;
    }
    memcpy(&req->buffer[req->len], ptr, realsize);
    req->len += realsize;
    req->buffer[req->len] = 0;

    return realsize;
}


int main(int argc, char **argv) {
    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();

    get_request req = {.buffer = NULL, .len = 0, .buflen = 0};

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "length: 20");
        headers = curl_slist_append(headers, "numbers: true");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        req.buffer = malloc(CHUNK_SIZE);
        req.buflen = CHUNK_SIZE;

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&req);

        res = curl_easy_perform(curl);
        printf("Result = %u\n",res);

        printf("Total received bytes: %zu\n", req.len);
        printf("Received data:/n%s\n", req.buffer);
        free(req.buffer);        
    }

    curl_easy_cleanup(curl);
}
输出:

receive chunk of 1256 bytes
Result = 0
Total received bytes: 1256
Received data:
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
GET请求完成后,您可以访问req->buffer中的数据,并解析JSON对象或任何其他数据。 需要添加realloc等的错误检查

我使用了一种方法,能够处理接收到的任何数量的块中的任何长度的内容。 如果您知道预期内容的长度,可以使用固定大小的缓冲区

正如您在我的示例中所看到的,在下载完成后,用户数据结构仍然存在,并且可以在curl\u easy\u perform返回后派生内容。

res是函数的结果代码,而不是来自HTTP服务器的响应。不能将其转换为字符串。您需要直接处理传入的数据。仔细看看res中的这个回调函数是函数的结果代码,而不是来自HTTP服务器的响应。不能将其转换为字符串。您需要直接处理传入的数据。请仔细查看中的回调函数