2015-08-25 12 views
8

Sto provando a leggere in un file JSON. Finora mi sono concentrato sull'utilizzo di jsoncpp. Tuttavia, sono molto nuovo in C++ e la documentazione è abbastanza difficile da capire per me. Qualcuno potrebbe forse spiegare in termini laici cosa fa?Leggere file json in C++

Dire che ho un people.json che assomiglia a questo:

{"Anna" : { 
     "age": 18, 
     "profession": "student"}, 
"Ben" : { 
     "age" : "nineteen", 
     "profession": "mechanic"} 
} 

cosa succede quando ho letto questo in? Posso creare una sorta di struttura dati people che posso indicizzare con Anna e Ben e age e profession? Quale sarebbe il tipo di dati di people? Ho pensato che sarebbe stato qualcosa di simile a una mappa (annidata), ma i valori delle mappe devono sempre avere lo stesso tipo, no?

Ho lavorato con Python prima e il mio "obiettivo" (che potrebbe essere impostato male per C++) è ottenere l'equivalente di un dizionario python annidato.

+0

FWIW: Ho usato questo C++ JSON parsing biblioteca con successo https://github.com/cierelabs/json_spirit –

+0

Si noti che JSON (contrariamente a JavaScript) richiede che le chiavi siano racchiuse tra virgolette doppie. –

risposta

6
  1. Sì, è possibile creare una struttura di dati annidata people che può essere indicizzato da Anna e Ben. Tuttavia, non è possibile indicizzarlo direttamente tramite age e profession (Verrà visualizzata questa parte nel codice).

  2. Il tipo di dati di people è di tipo Json::Value (definito in jsoncpp). Hai ragione, è simile alla mappa nidificata, ma Value è una struttura di dati definita in modo tale che è possibile memorizzare e accedere a più tipi. È simile a una mappa con un string come chiave e Json::Value come valore. Potrebbe anche essere una mappa tra unsigned int come chiave e Json::Value come valore (In caso di matrici json).

Ecco il codice:

#include <json/value.h> 
#include <fstream> 

std::ifstream people_file("people.json", std::ifstream::binary); 
people_file >> people; 

cout<<people; //This will print the entire json object. 

//The following lines will let you access the indexed objects. 
cout<<people["Anna"]; //Prints the value for "Anna" 
cout<<people["ben"]; //Prints the value for "Ben" 
cout<<people["Anna"]["profession"]; //Prints the value corresponding to "profession" in the json for "Anna" 

cout<<people["profession"]; //NULL! There is no element with key "profession". Hence a new empty element will be created. 

Come si può vedere, è possibile indicizzare l'oggetto JSON basato solo sulla gerarchia dei dati di input.

+0

Grazie! Capisco l'idea ora. Tuttavia, non funziona ancora abbastanza: se aggiungo 'json-forwards.h',' json.h' e 'jsoncpp.cpp' al progetto ottengo un messaggio di errore" Operandi non validi all'espressione binaria ('std :: ifstream e 'Json :: Value' "alla riga people_file >> persone Se aggiungo tutti i file in" include/"ricevo un messaggio di errore" Errore dal lettore: * Riga 1, colonna 1 Errore di sintassi: valore , oggetto o array previsto. " I percorsi di ricerca dell'intestazione sono impostati su" include/"e" dist/". – user3515814

+0

Suppongo che dovrai includere" json/json.h "anziché" json.h ". Non sono del tutto sicuro poiché è passato un po 'di tempo da quando ho usato jsoncpp.Ho trovato un'alternativa molto più semplice [nlohmann json] (https://github.com/nlohmann/json). Ha praticamente la stessa funzionalità ed è molto semplice da usare. Devi solo includere un singolo file, '#include '. Potresti volerlo dare un'occhiata –

3

Vedere this. Il modo più conveniente per lavorare con il formato JSON che ho trovato. È progettato per comportarsi proprio come un contenitore STL che rende il suo utilizzo molto intuitivo.

1

In sostanza javascript e C++ funzionano su due principi diversi. Javascript crea un "array associativo" o una tabella hash, che corrisponde a una chiave stringa, che è il nome del campo, a un valore. Il C++ stende le strutture in memoria, quindi i primi 4 byte sono un numero intero, che è un'età, quindi forse abbiamo una stringa a 32 byte fissa-wth che rappresenta la "professione".

Quindi javascript gestirà le cose come "età" di 18 in un record e "diciannove" in un altro. C++ non può. (Tuttavia C++ è molto più veloce).

Quindi, se vogliamo gestire JSON in C++, dobbiamo costruire l'array associativo da zero. Quindi dobbiamo taggare i valori con i loro tipi. È un numero intero, un valore reale (probabilmente ritorna come "doppio"), booleano, una stringa? Ne consegue che una classe JSON C++ è un bel pezzo di codice. In effetti ciò che stiamo facendo è implementare un po 'del motore javascript in C++. Quindi passiamo il nostro parser JSON al JSON come una stringa, e lo rende token e ci dà le funzioni per interrogare il JSON dal C++.

0

memorizzazione popoli come questo

{"Anna" : { 
    "age": 18, 
    "profession": "student"}, 
"Ben" : { 
    "age" : "nineteen", 
    "profession": "mechanic"} 
} 

causeranno problemi, in particolare se differenti popoli hanno stesso nome ..

piuttosto utilizzare la matrice oggetti memorizzazione come questo

{ 
    "peoples":[ 
     { 
      "name":"Anna", 
      "age": 18, 
      "profession": "student" 
     }, 
     { 
      "name":"Ben", 
      "age" : "nineteen", 
      "profession": "mechanic" 
     } 
    ] 
} 

come questo, può enumerare oggetti o accedere agli oggetti per indice numerico. ricorda che json è una struttura di archiviazione, non un sorter o un indicizzatore dinamico. utilizza i dati memorizzati in json per creare indici di cui hai bisogno e accedere ai dati.

0

Esempio (con il codice sorgente completo) per leggere un file di configurazione JSON:

https://github.com/sksodhi/CodeNuggets/tree/master/json/config_read

> pwd 
/root/CodeNuggets/json/config_read 
> ls 
Makefile README.md ReadJsonCfg.cpp cfg.json 
> cat cfg.json 
{ 
    "Note" : "This is a cofiguration file", 
    "Config" : { 
     "server-ip"  : "10.10.10.20", 
     "server-port" : "5555", 
     "buffer-length" : 5000 
    } 
} 
> cat ReadJsonCfg.cpp 
#include <iostream> 
#include <json/value.h> 
#include <jsoncpp/json/json.h> 
#include <fstream> 

void 
displayCfg(const Json::Value &cfg_root); 

int 
main() 
{ 
    Json::Reader reader; 
    Json::Value cfg_root; 
    std::ifstream cfgfile("cfg.json"); 
    cfgfile >> cfg_root; 

    std::cout << "______ cfg_root : start ______" << std::endl; 
    std::cout << cfg_root << std::endl; 
    std::cout << "______ cfg_root : end ________" << std::endl; 

    displayCfg(cfg_root); 
}  

void 
displayCfg(const Json::Value &cfg_root) 
{ 
    std::string serverIP = cfg_root["Config"]["server-ip"].asString(); 
    std::string serverPort = cfg_root["Config"]["server-port"].asString(); 
    unsigned int bufferLen = cfg_root["Config"]["buffer-length"].asUInt(); 

    std::cout << "______ Configuration ______" << std::endl; 
    std::cout << "server-ip  :" << serverIP << std::endl; 
    std::cout << "server-port :" << serverPort << std::endl; 
    std::cout << "buffer-length :" << bufferLen<< std::endl; 
} 
> cat Makefile 
CXX = g++ 
PROG = readjsoncfg 

CXXFLAGS += -g -O0 -std=c++11 

CPPFLAGS += \ 
     -I. \ 
     -I/usr/include/jsoncpp 

LDLIBS = \ 
       -ljsoncpp 

LDFLAGS += -L/usr/local/lib $(LDLIBS) 

all: $(PROG) 
     @echo $(PROG) compilation success! 

SRCS = \ 
     ReadJsonCfg.cpp 
OBJS=$(subst .cc,.o, $(subst .cpp,.o, $(SRCS))) 

$(PROG): $(OBJS) 
     $(CXX) $^ $(LDFLAGS) -o [email protected] 

clean: 
     rm -f $(OBJS) $(PROG) ./.depend 

depend: .depend 

.depend: $(SRCS) 
     rm -f ./.depend 
     $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $^ > ./.depend; 

include .depend 
> make 
Makefile:43: .depend: No such file or directory 
rm -f ./.depend 
g++ -g -O0 -std=c++11 -I. -I/usr/include/jsoncpp -MM ReadJsonCfg.cpp > ./.depend; 
g++ -g -O0 -std=c++11 -I. -I/usr/include/jsoncpp -c -o ReadJsonCfg.o ReadJsonCfg.cpp 
g++ ReadJsonCfg.o -L/usr/local/lib -ljsoncpp -o readjsoncfg 
readjsoncfg compilation success! 
> ./readjsoncfg 
______ cfg_root : start ______ 
{ 
     "Config" : 
     { 
       "buffer-length" : 5000, 
       "server-ip" : "10.10.10.20", 
       "server-port" : "5555" 
     }, 
     "Note" : "This is a cofiguration file" 
} 
______ cfg_root : end ________ 
______ Configuration ______ 
server-ip  :10.10.10.20 
server-port :5555 
buffer-length :5000 
> 
+0

Grazie per un swer, puoi condividere il motivo per cui lo stai offrendo come risposta per fornire un contesto all'utente. – Daniel

+0

@Daniel Ho aggiunto il contesto ("per leggere un file di configurazione di JSON"). –