2010-12-14 11 views
5

Estoy tratando de usar jsoncpp para analizar un conjunto de json. El json se ha generado a partir de una página web con simplejson de un objeto django. Lo obtengo de una URL particular usando libcurl. Cuando utilizo la función toStyledString() en la raíz, obtengo esta impresión.Problemas para obtener un nodo de JSON con jsoncpp

[ 
    { 
     "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 
    } 
] 

Parece que estoy obteniendo los datos correctos y está en una clase Json :: Value.

El problema es que no puedo sacar un nodo en particular de la estructura json. Este es el código que estoy usando.

#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; 
} 

debido a otro problema que no estoy usando la biblioteca compartida libjson.so real, soy sólo tirando de los archivos y la compilación de ellas con mi fuente (supongo que esto es malo, pero el problema es no es el punto de esta pregunta). A continuación se muestra cómo está estructurada mi carpeta 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 

y esta es la salida de make.

[email protected]:/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 

y de todo eso me da la siguiente salida cuando ejecuto 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 
    } 
] 

no consigo el problema si comento hacia fuera esta línea

const Json::Value fields = root["songs"]; 

Im totalmente abierto a el hecho de que estoy haciendo algo mal aquí. Pero simplemente no sé qué es. Entonces, ¿cuál es la causa del error:

Bird: ../src/lib_json/json_value.cpp:1025: Json::Value& Json::Value::resolveReference(const char*, bool): Assertion `type_ == nullValue || type_ == objectValue' failed. 

gracias por cualquier ayuda que pueda dar.

Saludos

Marcos

Respuesta

7

Así que una vez más fue un caso de no entender lo que estaba pasando.

Como mi estructura json era de un modelo de Django, en realidad era una matriz de json (sé que voy a poner la terminología equivocada aquí, y me disculpo por adelantado).Esto podría ser encontrado a partir del código siguiente:

cout << "type: " << root.type() << endl; 

con la siguiente salida

type: 6 

en jsoncpp, esto significa una gran variedad de JSON. Esto también se puede deducir del estilo de salida de los corchetes iniciales y finales. También desde esta enumeración en value.h a partir de la línea 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). 
    }; 

Esto era más difícil de decir, porque sólo tenía una fila de datos que salen de mi modelo de Django en el momento. Como entiendo ahora, estaba tratando de hacer una operación para una estructura json de tipo objectValue, cuando realmente necesitaba seleccionar la posición inicial de la matriz primero.

Para obtener realmente en la url tengo que hacer algo como esto.

for(int i = 0; i < root.size(); i++) 
    { 
     cout << root[i]["fields"]["url"].asString() << endl; 
    } 

que le llevará

http://192.168.0.5:8000/CarolKing 
http://192.168.0.5:8000/CarolKing2 

desde el siguiente 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 poner esto aquí, así que si alguien viene a través de este que al menos tendrán alguna forma de encontrar fuera lo que está mal.

Saludos

Marcar

1

Lo sentimos,

Pero

const Json::Value fields = root["songs"]; 

no debe ser

const Json::Value fields = root["fields"]; 

canciones se anida en los campos, así que para obtener las canciones debe acceder de esta manera:

const Json::Value songs = root["fields"]["songs"]; 

¿No?

+0

si esa es la derecha. Pero sigo teniendo el mismo error. Actualizaré el Código en las preguntas. Buen lugar, aunque! –

+1

El problema es que el JSON devuelto por el servidor está envuelto en una matriz: [{"fields": ....}], es por eso que la afirmación falla ... –

Cuestiones relacionadas