Im trying to use jsoncpp to parse a set of json. The json has been generated from a webpage with simplejson from a django object. I get it from a particular URL using libcurl. WHen I use the toStyledString() function on the root I get this printed out.
[
{
"fields" : {
"desc" : "Carol King test",
"format" : "1",
"genre" : "Pop",
"mount" : "CarolKing",
"name" : "Carol King",
"protocol" : "0",
"songs" : [ 27, 28, 29, 30, 31, 32, 33, 34 ],
"url" : "http://192.168.0.5:8000/CarolKing"
},
"model" : "music.playlist",
"pk" : 2
}
]
So it seems like I am getting the data right and its in a Json::Value class.
The problem is that im unable to get a particular node out of the json structure. This is the code im using.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <curl/curl.h>
#include <string>
#include "Parameter.h"
#include "lib_json/json.h"
using namespace std;
static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
cout << "-->write_data " << endl;
string buf = string(static_cast<char *>(ptr), size *nmemb);
stringstream * response = static_cast<stringstream *>(stream);
response->write(buf.c_str(), (streamsize)buf.size());
return size * nmemb;
}
int main(int sys_argc, char ** sys_argv) {
CURL *curl;
CURLcode res;
stringstream response;
string error;
char ** argv = sys_argv;
string file = argv[1];
Parameter *parms = new Parameter(file);
parms->ReadParameters();
cout << "URL: " << parms->GetParameter("URL");
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, parms->GetParameter("URL").c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
res = curl_easy_perform(curl);
cout << "Playlists-JSON: " << response.str() << endl;
curl_easy_cleanup(curl);
}
Json::Value root;
Json::Reader reader;
bool parsingSuccessful = reader.parse(response.str(), root);
if(!parsingSuccessful)
{
cout << "Failed to parse configuration. " << reader.getFormatedErrorMessages();
return 16;
}
cout << "Pretty-Print: " << root.toStyledString() << endl;
const Json::Value fields = root["fields"]["songs"];
return 0;
}
because of another issue I'm not using the actual libjson.so shared library, im just pulling in the files and compiling them in with my source (I'm guessing this is bad, but that problem is not the point of this question). Below is how my src folder is structured.
.:
bird Bird.cpp fopen.cpp fopen.h lib_json Parameter.cpp Parameter.h
./lib_json:
autolink.h features.h json_batchallocator.h json_internalarray.inl json_reader.cpp json_valueiterator.inl reader.h value.h
config.h forwards.h json.h json_internalmap.inl json_value.cpp json_writer.cpp sconscript writer.h
and this is the output of make.
munderwo@bertha:/local/Documents/inthebackground/Box/Bird/bird/Debug$ make
Building file: ../src/lib_json/json_reader.cpp
Invoking: GCC C++ Compiler
g++ -I"/local/Documents/inthebackground/Box/Bird/bird/Libraries/i386/include" -I"/local/Documents/inthebackground/Box/Bird/bird/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/lib_json/json_reader.d" -MT"src/lib_json/json_reader.d" -o"src/lib_json/json_reader.o" "../src/lib_json/json_reader.cpp"
Finished building: ../src/lib_json/json_reader.cpp
Building file: ../src/lib_json/json_value.cpp
Invoking: GCC C++ Compiler
g++ -I"/local/Documents/inthebackground/Box/Bird/bird/Libraries/i386/include" -I"/local/Documents/inthebackground/Box/Bird/bird/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/lib_json/json_value.d" -MT"src/lib_json/json_value.d" -o"src/lib_json/json_value.o" "../src/lib_json/json_value.cpp"
Finished building: ../src/lib_json/json_value.cpp
Building file: ../src/lib_json/json_writer.cpp
Invoking: GCC C++ Compiler
g++ -I"/local/Documents/inthebackground/Box/Bird/bird/Libraries/i386/include" -I"/local/Documents/inthebackground/Box/Bird/bird/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/lib_json/json_writer.d" -MT"src/lib_json/json_writer.d" -o"src/lib_json/json_writer.o" "../src/lib_json/json_writer.cpp"
Finished building: ../src/lib_json/json_writer.cpp
Building file: ../src/Bird.cpp
Invoking: GCC C++ Compiler
g++ -I"/local/Documents/inthebackground/Box/Bird/bird/Libraries/i386/include" -I"/local/Documents/inthebackground/Box/Bird/bird/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Bird.d" -MT"src/Bird.d" -o"src/Bird.o" "../src/Bird.cpp"
Finished building: ../src/Bird.cpp
Building file: ../src/Parameter.cpp
Invoking: GCC C++ Compiler
g++ -I"/local/Documents/inthebackground/Box/Bird/bird/Libraries/i386/include" -I"/local/Documents/inthebackground/Box/Bird/bird/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Parameter.d" -MT"src/Parameter.d" -o"src/Parameter.o" "../src/Parameter.cpp"
../src/Parameter.cpp: In member function ‘int Parameter::ReadParameters()’:
../src/Parameter.cpp:47: warning: comparison between signed and unsigned integer expressions
Finished building: ../src/Parameter.cpp
Building file: ../src/fopen.cpp
Invoking: GCC C++ Compiler
g++ -I"/local/Documents/inthebackground/Box/Bird/bird/Libraries/i386/include" -I"/local/Documents/inthebackground/Box/Bird/bird/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/fopen.d" -MT"src/fopen.d" -o"src/fopen.o" "../src/fopen.cpp"
Finished building: ../src/fopen.cpp
Building target: Bird
Invoking: GCC C++ Linker
g++ -L"/local/Documents/inthebackground/Box/Bird/bird/Libraries/i386/lib" -o"Bird" ./src/lib_json/json_reader.o ./src/lib_json/json_value.o ./src/lib_json/json_writer.o ./src/Bird.o ./src/Parameter.o ./src/fopen.o -lcurl
Finished building target: Bird
and from all of that I get the following output when I execute Bird
*Bird: ../src/lib_json/json_value.cpp:1025: Json::Value& Json::Value::resolveReference(const char*, bool): Assertion `type_ == nullValue || type_ == objectValue' failed.*
URL: 127.0.0.1:8000/playlist-->write_data
Playlists-JSON: [{"pk": 2, "model": "music.playlist", "fields": {"protocol": "0", "name": "Carol King", "format": "1", "url": "http://192.168.0.5:8000/CarolKing", "mount": "CarolKing", "genre": "Pop", "songs": [27, 28, 29, 30, 31, 32, 33, 34], "desc": "Carol King test"}}]
Pretty-Print: [
{
"fields" : {
"desc" : "Carol King test",
"format" : "1",
"genre" : "Pop",
"mount" : "CarolKing",
"name" : "Carol King",
"protocol" : "0",
"songs" : [ 27, 28, 29, 30, 31, 32, 33, 34 ],
"url" : "http://192.168.0.5:8000/CarolKing"
},
"model" : "music.playlist",
"pk" : 2
}
]
I dont get the problem if I comment out this line
const Json::Value fields = root["songs"];
Im totally open to the fact that im doing something wrong here. But I just dont know what it is. So what is causing the error:
Bird: ../src/lib_json/json_value.cpp:1025: Json::Value& Json::Value::resolveReference(const char*, bool): Assertion `type_ == nullValue || type_ == objectValue' failed.
thanks for any help you can give.
Cheers
Mark
So once again it was a case of not understanding what was going on.
Because my json structure was from a Django model it was actually and array of json (I know im going to get the terminology wrong here, and I apologize in advance). This could be found from the following code:
cout << "type: " << root.type() << endl;
with the following output
type: 6
in jsoncpp, this means an array of json. This can also be infered from the Styledoutput from the starting and ending square brackets. Also from this enum in value.h starting on line 23
enum ValueType
{
nullValue = 0, ///< 'null' value
intValue, ///< signed integer value
uintValue, ///< unsigned integer value
realValue, ///< double value
stringValue, ///< UTF-8 string value
booleanValue, ///< bool value
arrayValue, ///< array value (ordered list)
objectValue ///< object value (collection of name/value pairs).
};
This was harder to tell because I only had one row of data coming out of my Django Model at the time. As I understand now, I was trying to do an operation for an objectValue type json structure, when I really needed to select the initial array position first.
So to actually get at the url I need to do something like this.
for(int i = 0; i < root.size(); i++)
{
cout << root[i]["fields"]["url"].asString() << endl;
}
which will get you
http://192.168.0.5:8000/CarolKing
http://192.168.0.5:8000/CarolKing2
from the following json
[
{
"fields" : {
"desc" : "Carol King test",
"format" : "1",
"genre" : "Pop",
"mount" : "CarolKing",
"name" : "Carol King",
"protocol" : "0",
"songs" : [ 27, 28, 29, 30, 31, 32, 33, 34 ],
"url" : "http://192.168.0.5:8000/CarolKing"
},
"model" : "music.playlist",
"pk" : 2
},
{
"fields" : {
"desc" : "Second carol King",
"format" : "1",
"genre" : "Pop",
"mount" : "CarolKing2",
"name" : "Carol King 2",
"protocol" : "0",
"songs" : [ 26, 27, 28, 29, 30 ],
"url" : "http://192.168.0.5:8000/CarolKing2"
},
"model" : "music.playlist",
"pk" : 35
}
]
Im putting this here so that if anyone else comes across this they will at least have some way of finding out what is wrong.
Cheers
Mark