Чтение файлов json на C++
Я пытаюсь прочитать в файле JSON. До сих пор я сосредоточился на использовании jsoncpp
библиотека. Тем не менее, документация довольно трудно понять для меня. Может ли кто-нибудь объяснить в светских терминах, что он делает?
скажем, у меня есть people.json
выглядит так:
{"Anna" : {
"age": 18,
"profession": "student"},
"Ben" : {
"age" : "nineteen",
"profession": "mechanic"}
}
что происходит, когда я читаю это? Могу ли я создать какую-то структуру данных people
который я могу индексировать по Anna
и Ben
а также age
и profession
? Каким будет тип данных people
? Я думал, что это будет что-то похожее на (вложенную) карту, но Значения карты всегда должны иметь один и тот же тип, не так ли?
я работал с python раньше, и моя "цель" (которая может быть плохо установлена для C++)-получить эквивалент вложенного словаря python.
5 ответов
Да, вы можете создать вложенную структуру данных
people
, который может быть проиндексированAnna
иBen
. Однако, вы не можете индексировать его напрямую поage
иprofession
(Я вернусь к этой части кода).тип данных
people
типаJson::Value
(который определен в jsoncpp). Вы правы, это похоже на вложенную карту, ноValue
- это структура данных, которая определяется таким образом, что несколько типов могут быть сохранены и доступны. Он похож на карту сstring
как ключ иJson::Value
как значение. Это также может быть карта междуunsigned int
как ключ иJson::Value
как значение (в случае массивов json).
вот код:
#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.
как вы можете видеть, вы можете индексировать объект json только на основе иерархии входных данных.
посмотреть репозиторий JSON nlohmann на GitHub. Я обнаружил, что это самый удобный способ работы с JSON.
Он разработан, чтобы вести себя так же, как контейнер STL, что делает его использование очень интуитивным.
по существу javascript и C++ работают на двух разных принципах. Javascript создает "ассоциативный массив" или хэш-таблицу, которая соответствует строковому ключу, который является именем Поля, значению. C++ выкладывает структуры в память, поэтому первые 4 байта-это целое число, которое является возрастом, тогда, возможно, у нас есть фиксированная 32-байтовая строка, которая представляет "профессию".
таким образом, javascript будет обрабатывать такие вещи, как" возраст "18 в одной записи и" девятнадцать " в другой. C++ не может. (Однако C++ намного быстрее).
Итак, если мы хотим обрабатывать JSON в C++, мы должны построить ассоциативный массив с нуля. Затем мы должны пометить значения их типами. Это целое число, реальное значение (возможно, возвращаемое как "double"), логическое, строка? Из этого следует, что класс JSON C++ является довольно большим куском кода. Эффективно то, что мы делаем, - это реализация немного движка javascript на C++. Мы затем передаем наш формат JSON парсер JSON в виде строки, и он tokenises его, и дает нам функции для запроса JSON из C++.
пример (с полным исходным кодом) для чтения файла конфигурации 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 $@
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
>
хранение людей, как это
{"Anna" : {
"age": 18,
"profession": "student"},
"Ben" : {
"age" : "nineteen",
"profession": "mechanic"}
}
вызовет проблемы, особенно если разные народы имеют одинаковое имя..
скорее используйте массив, хранящий такие объекты
{
"peoples":[
{
"name":"Anna",
"age": 18,
"profession": "student"
},
{
"name":"Ben",
"age" : "nineteen",
"profession": "mechanic"
}
]
}
таким образом, вы можете перечислять объекты или получать объекты по числовому индексу. помните, что json-это структура хранения, а не динамический сортировщик или индексатор. используйте данные, хранящиеся в json, для построения индексов по мере необходимости и доступа к данным.