【问题标题】:c++ rapidjson parse error of CURLOPTS contentc++ rapidjson解析CURLOPTS内容错误
【发布时间】:2014-10-24 22:58:47
【问题描述】:

我正在尝试反序列化从 CURLOPTS 获得的 json 对象,但出现解析错误(错误的数据类型)。 如何将 JSON 转换为标准 c++ 对象或可读变量?

代码:

darknet064tokyo rapidjson # cat testGetprice.cpp
#include "include/rapidjson/document.h"
#include <iostream>
#include <stdio.h>
#include <curl/curl.h>
#include <unistd.h>
#include <unordered_map>

using namespace rapidjson;

size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
        size_t written;
        written = fwrite(ptr, size, nmemb, stream);
        return written;
}
//function to get coin data and perform analysis
int getData()
{
        int count = 0;
        //begin non terminating loop
        while(true)
        {
                count++;
                CURL *curl;
                CURLcode res;
                curl = curl_easy_init();
                if(curl) {
                        curl_easy_setopt(curl, CURLOPT_URL, "http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=155");
                        /* Perform the request, res will get the return code */
                        res = curl_easy_perform(curl);
                        /* Check for errors */
                        if(res != CURLE_OK)
                                fprintf(stderr, "curl_easy_perform() failed: %s\n",
                                curl_easy_strerror(res));
                        //begin deserialization
                        Document document;
                        document.Parse(res);
                        assert(document.HasMember("lasttradeprice"));
                        assert(document["hello"].IsString());
                        printf("The Last Traded Price is = %s\n", document["lasttradeprice"].GetString());


                        FILE * pFile;
                        pFile = fopen ("/home/coinz/cryptsy/myfile.txt","a+");
                        if (pFile!=NULL)
                        {
                                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
                                curl_easy_setopt(curl, CURLOPT_WRITEDATA, pFile);
                                res = curl_easy_perform(curl);
                                //std::cout << pFile << std::endl;
                                fprintf(pFile, "\n");
                                fclose (pFile);
                        }
                        /* always cleanup */
                        curl_easy_cleanup(curl);
                //timer for URL request.  *ADUJST ME AS DESIRED*
                usleep(10000000);
                }
        }
        return 0;
}

//Le Main
int main(void){
        getData();
}

错误码输出:

darknet064tokyo rapidjson # g++ -g testGetprice.cpp -o testGetprice.o -std=gnu++11
testGetprice.cpp: In function 'int getData()':
testGetprice.cpp:36:22: error: no matching function for call to 'rapidjson::GenericDocument<rapidjson::UTF8<> >::Parse(CURLcode&)'
testGetprice.cpp:36:22: note: candidates are:
In file included from testGetprice.cpp:1:0:
include/rapidjson/document.h:1723:22: note: template<unsigned int parseFlags, class SourceEncoding> rapidjson::GenericDocument& rapidjson::GenericDocument::Parse(const Ch*) [with unsigned int parseFlags = parseFlags; SourceEncoding = SourceEncoding; Encoding = rapidjson::UTF8<>; Allocator = rapidjson::MemoryPoolAllocator<>; StackAllocator = rapidjson::CrtAllocator]
include/rapidjson/document.h:1723:22: note:   template argument deduction/substitution failed:
testGetprice.cpp:36:22: note:   cannot convert 'res' (type 'CURLcode') to type 'const Ch* {aka const char*}'
In file included from testGetprice.cpp:1:0:
include/rapidjson/document.h:1734:22: note: template<unsigned int parseFlags> rapidjson::GenericDocument& rapidjson::GenericDocument::Parse(const Ch*) [with unsigned int parseFlags = parseFlags; Encoding = rapidjson::UTF8<>; Allocator = rapidjson::MemoryPoolAllocator<>; StackAllocator = rapidjson::CrtAllocator]
include/rapidjson/document.h:1734:22: note:   template argument deduction/substitution failed:
testGetprice.cpp:36:22: note:   cannot convert 'res' (type 'CURLcode') to type 'const Ch* {aka const char*}'
In file included from testGetprice.cpp:1:0:
include/rapidjson/document.h:1741:22: note: rapidjson::GenericDocument<Encoding, Allocator, StackAllocator>& rapidjson::GenericDocument<Encoding, Allocator, StackAllocator>::Parse(const Ch*) [with Encoding = rapidjson::UTF8<>; Allocator = rapidjson::MemoryPoolAllocator<>; StackAllocator = rapidjson::CrtAllocator; rapidjson::GenericDocument<Encoding, Allocator, StackAllocator> = rapidjson::GenericDocument<rapidjson::UTF8<> >; rapidjson::GenericDocument<Encoding, Allocator, StackAllocator>::Ch = char]
include/rapidjson/document.h:1741:22: note:   no known conversion for argument 1 from 'CURLcode' to 'const Ch* {aka const char*}'

【问题讨论】:

    标签: c++ json serialization utf-8 libcurl


    【解决方案1】:

    注意你在做什么。 curl_easy_perform() 返回一个错误代码,而不是服务器的响应数据。您将 Curl 的错误代码传递给 Document::Parse(),而不是实际的 JSON 数据。错误消息准确地告诉您:

    错误:没有匹配函数调用 'rapidjson::GenericDocument >::Parse(CURLcode&)'

    默认情况下,curl_easy_perform() 将接收到的数据输出到标准输出。要覆盖它以便您可以在代码中接收 JSON 数据,您需要使用 curl_easy_setopt() 分配自定义 CURLOPT_WRITEFUNCTION 回调,将接收到的数据写入您使用 CURLOPT_WRITEDATA 指定的缓冲区/字符串。您已经这样做了,但是您正在将数据写入文件,而不是内存缓冲区/字符串。

    libCurl tutorial 的“处理 Easy libcurl”部分讨论了这种情况。

    试试这样的:

    #include "include/rapidjson/document.h"
    #include <iostream>
    #include <stdio.h>
    #include <curl/curl.h>
    #include <unistd.h>
    #include <unordered_map>
    #include <string>
    
    using namespace rapidjson;
    
    struct myData
    {
        std::fstream *file;
        std::string *str;
    };
    
    size_t write_data(void *ptr, size_t size, size_t nmemb, myData *data)
    {
        size_t numBytes = size * nmemb;
    
        if (data->file)
            data->file->write((char*)ptr, numBytes);
    
        if (data->str)
            *(data->str) += std::string((char*)ptr, numBytes);
    
        return numBytes;
    }
    
    //function to get coin data and perform analysis
    int getData()
    {
        int count = 0;
    
        //begin non terminating loop
        while(true)
        {
            count++;
            CURL *curl = curl_easy_init();
            if (curl)
            {
                curl_easy_setopt(curl, CURLOPT_URL, "http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=155");
    
                std::fstream file("/home/coinz/cryptsy/myfile.txt", ios_base::out | ios_base::ate);
                std::string json;
    
                myData data;
                data.file = &file;
                data.str = &json;
    
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data);
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
    
                /* Perform the request, res will get the return code */
                CURLcode res = curl_easy_perform(curl);
    
                /* Check for errors */
                if (res != CURLE_OK)
                {
                    std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
                }
                else
                {
                    file << std::endl;
    
                    //begin deserialization
                    Document document;
                    document.Parse(json.c_str());
                    assert(document.HasMember("lasttradeprice"));
                    assert(document["hello"].IsString());
                    std::cout << "The Last Traded Price is = " << document["lasttradeprice"].GetString() << std::endl;
                }
    
                /* always cleanup */
                curl_easy_cleanup(curl);
            }
    
            //timer for URL request.  *ADUJST ME AS DESIRED*
            usleep(10000000);
        }
    
        return 0;
    }
    
    //Le Main
    int main(void)
    {
        getData();
    }
    

    【讨论】:

    • 新错误,但请注意:无法将 'res' (type 'CURLcode') 转换为 type 'const Ch* {aka const char*}' hmmm
    • 看起来有些版本冲突paste.ee/p/Jzjvx 错误:'data->myData::str += std::basic_string 中的 'operator+=' 不匹配
    • document.Parse(json.c_str());似乎是空的
    • 什么似乎是空的? json 还是 document?您是否确认在 curl_easy_perform() 工作时调用了 write_data()
    • bpaste.net/show/fceeeae8511f 生产 -> testGetprice3.o: testGetprice3.cpp:71: int getData(): Assertion `document["success"].IsString()' 失败。在执行/运行时。不过没有编译错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 2016-03-07
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多