Проблемы с получением узла из JSON с помощью jsoncpp
Я пытаюсь использовать jsoncpp для анализа набора JSON. JSON был сгенерирован из веб-страницы с simplejson из объекта Django. Я получаю его с определенного URL, используя libcurl. Когда я использую функцию toStyledString() в корне, я распечатываю это.
[
{
"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
}
]
Похоже, я правильно понял данные в классе Json::Value.
Проблема в том, что я не могу получить конкретный узел из структуры json. Это код, который я использую.
#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;
}
из-за другой проблемы я не использую настоящую разделяемую библиотеку libjson.so, я просто извлекаю файлы и собираю их с моим источником (полагаю, это плохо, но проблема не в этом вопросе), Ниже показано, как структурирована моя папка src.
.:
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
и это вывод 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
и из всего этого я получаю следующий вывод при выполнении 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
}
]
Я не понимаю проблему, если я закомментирую эту строку
const Json::Value fields = root["songs"];
Я полностью открыт к тому, что я делаю что-то не так здесь. Но я просто не знаю, что это. Итак, что вызывает ошибку:
Bird: ../src/lib_json/json_value.cpp:1025: Json::Value& Json::Value::resolveReference(const char*, bool): Assertion `type_ == nullValue || type_ == objectValue' failed.
спасибо за любую помощь, которую вы можете оказать.
ура
отметка
2 ответа
Итак, еще раз это был случай непонимания того, что происходит.
Поскольку моя структура json была взята из модели Django, на самом деле это был массив json (я знаю, что здесь я неправильно понял терминологию, и я заранее извиняюсь). Это можно найти из следующего кода:
cout << "type: " << root.type() << endl;
со следующим выводом
type: 6
в jsoncpp это означает массив json. Это также может быть выведено из Styledoutput из начальных и конечных квадратных скобок. Также из этого перечисления в value.h, начиная со строки 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).
};
Об этом было сложнее сказать, потому что в то время у меня была только одна строка данных из моей модели Django. Как я теперь понимаю, я пытался выполнить операцию для структуры json типа objectValue, когда мне действительно нужно было сначала выбрать начальную позицию массива.
Таким образом, чтобы получить URL, мне нужно сделать что-то вроде этого.
for(int i = 0; i < root.size(); i++)
{
cout << root[i]["fields"]["url"].asString() << endl;
}
который получит тебя
http://192.168.0.5:8000/CarolKing
http://192.168.0.5:8000/CarolKing2
из следующего 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
}
]
Я помещаю это здесь так, чтобы, если кто-то еще сталкивался с этим, у них был по крайней мере какой-то способ узнать, что не так.
ура
отметка
Сожалею,
Но
const Json::Value fields = root["songs"];
Не должно быть
const Json::Value fields = root["fields"];
Песни вложены в поля, поэтому чтобы получить песни, вы должны получить к ним доступ следующим образом:
const Json::Value songs = root["fields"]["songs"];
Нет?