2015-08-25 19 views
8

Ich versuche, in einer JSON-Datei zu lesen. Bisher habe ich mich auf die Verwendung von jsoncpp konzentriert. Ich bin jedoch sehr neu in C++ und die Dokumentation ist für mich ziemlich schwer zu verstehen. Könnte jemand vielleicht laienhaft erklären, was es tut?JSON-Dateien in C++ lesen

sagen, dass ich eine people.json haben, die wie folgt aussieht:

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

Was passiert, wenn ich das in gelesen haben? Kann ich eine Art Datenstruktur people erstellen, die ich durch Anna und Ben sowie age und profession indexieren kann? Was wäre der Datentyp people? Ich dachte, es wäre etwas ähnlich wie eine (verschachtelte) Karte, aber Kartenwerte müssen immer den gleichen Typ haben, nicht wahr?

Ich habe vorher mit Python gearbeitet und mein "Ziel" (das für C++ schlecht eingestellt sein kann) ist, das Äquivalent eines verschachtelten Python-Wörterbuchs zu erhalten.

+0

FWIW: i dieses C verwendet haben ++ json Bibliothek mit Erfolg Parsen https://github.com/cierelabs/json_spirit –

+0

Bitte beachten Sie, dass JSON (im Gegensatz zu JavaScript) erfordert, dass Schlüssel in Anführungszeichen gesetzt werden. –

Antwort

6
  1. Ja, Sie können eine verschachtelte Datenstruktur people schaffen, die durch Anna und Ben indiziert werden können. Sie können es jedoch nicht direkt durch age und profession indizieren (ich werde zu diesem Teil im Code gelangen). Der Datentyp people ist vom Typ Json::Value (der in jsoncpp definiert ist). Sie haben Recht, es ist ähnlich der verschachtelten Karte, aber Value ist eine Datenstruktur, die so definiert ist, dass mehrere Typen gespeichert und zugegriffen werden können. Es ist ähnlich einer Karte mit einer string als Schlüssel und Json::Value als Wert. Es könnte auch eine Karte zwischen einem unsigned int als Schlüssel und Json::Value als Wert sein (im Falle von JSON-Arrays).

Hier ist der Code:

#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. 

Wie Sie sehen können, können Sie Index der JSON-Objekt in der Hierarchie der Eingabedaten nur berechnet.

+0

Danke! Ich verstehe die Idee jetzt. Es funktioniert jedoch noch nicht ganz: Wenn ich nur 'json-forwards.h',' json.h' und 'jsoncpp.cpp' zum Projekt hinzufüge, bekomme ich eine Fehlermeldung" Ungültige Operanden für binären Ausdruck ('std :: ifstream und 'Json :: Value' "in der Zeile people_file >> people. Wenn ich alle Dateien in' include/'hinzufüge, erhalte ich die Fehlermeldung" Fehler beim Lesen: * Zeile 1, Spalte 1 Syntaxfehler: Wert , Objekt oder Array erwartet. " Header-Suchpfade werden auf 'include /' und 'dist /' gesetzt. – user3515814

+0

Ich schätze, Sie müssen' json/json.h' anstelle von 'json.h' hinzufügen. Ich bin nicht ganz sicher, da es eine Weile her ist, seit ich jsoncpp benutzt habe. Ich fand eine viel einfachere Alternative [https://github.com/nlohmann/json]. Sie hat ziemlich die gleiche Funktionalität und ist sehr einfach Sie müssen nur eine einzelne Datei einschließen, '#include '. Sie können es sich ansehen. –

3

Betrachten Sie this. Die bequemste Art, mit dem json-Format zu arbeiten, habe ich gefunden. Es verhält sich wie ein STL-Container, was seine Verwendung sehr intuitiv macht.

1

Im Wesentlichen arbeiten Javascript und C++ auf zwei verschiedenen Prinzipien. Javascript erstellt eine "assoziative Matrix" oder eine Hash-Tabelle, die einen String-Schlüssel, der den Feldnamen darstellt, mit einem Wert vergleicht. C++ legt Strukturen im Speicher an, so dass die ersten 4 Bytes eine Ganzzahl sind, die ein Alter ist, dann haben wir vielleicht eine feste 32-Byte-Zeichenfolge, die den "Beruf" darstellt.

So Javascript wird Dinge wie "Alter" handhaben, 18 in einer Aufzeichnung und "neunzehn" in einer anderen zu sein. C++ kann nicht. (Allerdings ist C++ viel schneller).

Wenn wir also mit JSON in C++ umgehen wollen, müssen wir das assoziative Array von Grund auf aufbauen. Dann müssen wir die Werte mit ihren Typen kennzeichnen. Ist es eine ganze Zahl, ein reeller Wert (wahrscheinlich als "double"), boolean, eine Zeichenkette? Daraus folgt, dass eine JSON C++ - Klasse ziemlich viel Code enthält. Effektiv implementieren wir ein bisschen Javascript in C++. Dann übergeben wir unserem JSON-Parser den JSON als String, der ihn mit einem Token belegt und Funktionen zur Abfrage des JSON aus C++ bereitstellt.

0

Speicherung Völker wie diese

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

wird Probleme verursachen, insbesondere wenn differents Völker denselben Namen haben ..

eher verwenden Array speichern Objekte wie dieses

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

wie diese, Sie kann Objekte aufzählen oder Objekte mit numerischem Index aufrufen. Denken Sie daran, dass JSON Storage-Struktur, nicht dynamisch Sortierer oder Indexer ist. Verwenden Sie Daten, die in JSON gespeichert sind, um Indizes nach Bedarf zu erstellen und auf Daten zuzugreifen.

0

Beispiel (mit kompletten Source-Code) eine json Konfigurationsdatei zu lesen:

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

Vielen Dank für ein swer, können Sie teilen, warum Sie dies als die Antwort anbieten, um einen Kontext für den Benutzer bereitzustellen. – Daniel

+0

@Daniel Ich habe den Kontext hinzugefügt ("um eine JSON-Konfigurationsdatei zu lesen"). –