Reputation:
I am trying to deserialize a json object that I get from CURLOPTS and I am getting a parse error (wrong data type). How do I get the JSON into a standard c++ object or readable variable?
code:
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();
}
error code output:
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*}'
Upvotes: 0
Views: 1866
Reputation: 595320
Pay attention to what you are doing. curl_easy_perform()
returns an error code, not the server's response data. You are passing Curl's error code to Document::Parse()
, not the actual JSON data. The error messages are telling you exactly that:
error: no matching function for call to 'rapidjson::GenericDocument >::Parse(CURLcode&)'
By default, curl_easy_perform()
outputs the received data to stdout. To override that so you can receive the JSON data in your code, you need to use curl_easy_setopt()
to assign a custom CURLOPT_WRITEFUNCTION
callback that writes the received data to a buffer/string you specify using CURLOPT_WRITEDATA
. You are already doing that, but you are writing the data to a file, not to a memory buffer/string.
This type of situation is discussed in the "Handle the Easy libcurl" section of the libCurl tutorial.
Try something more like this:
#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();
}
Upvotes: 1