2014-10-24 3 views
0

Я пытаюсь десериализовать json-объект, который я получаю из CURLOPTS, и получаю ошибку синтаксического анализа (неправильный тип данных). Как получить JSON в стандартный объект C++ или читаемую переменную?C++ rapidjson parse error of CURLOPTS content

код:

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*}' 

ответ

1

Обратите внимание на то, что вы делаете. curl_easy_perform() возвращает код ошибки , а не данные ответа сервера. Вы передаете код ошибки Curl в Document::Parse(), а не фактические данные JSON. Сообщения об ошибках точно, что говорит вам:

error: no matching function for call to 'rapidjson::GenericDocument >::Parse(CURLcode&)'

По умолчанию curl_easy_perform() выводит полученные данные в стандартный вывод. Чтобы переопределить это, чтобы вы могли получать данные JSON в своем коде, вам необходимо использовать curl_easy_setopt() для назначения настраиваемого обратного вызова CURLOPT_WRITEFUNCTION, который записывает полученные данные в указанный вами буфер/строку с помощью CURLOPT_WRITEDATA. Вы уже это делаете, но вы записываете данные в файл, а не в буфер/строку памяти.

Этот тип ситуации обсуждается в разделе «Обрабатывать Easy libcurl» в libCurl tutorial.

Попробуйте что-то больше, как это:

#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(); 
} 
+0

новая ошибка, хотя примечание: не может преобразовать 'Рез' (типа 'CURLcode') к типу 'сопзЬ Ch * {ака Const символ *}' Ммм –

+0

Смотрите мой последний редактирует. –

+0

выглядит как конфликт какой-то версии http://paste.ee/p/Jzjvx error: нет соответствия для 'operator + =' in 'data-> myData :: str + = std :: basic_string –