我试图读取JSON文件。到目前为止,我一直专注于使用jsoncpp
库。但是,我很难理解文档。任何人都可以用非专业术语解释它的作用吗?
说我有people.json
,如下所示:
{"Anna" : {
"age": 18,
"profession": "student"},
"Ben" : {
"age" : "nineteen",
"profession": "mechanic"}
}
当我读到这个时会发生什么?我可以创建某种数据结构people
,我可以按Anna
和Ben
以及age
和profession
进行索引吗? people
的数据类型是什么?我认为它会类似于(嵌套)地图,但地图值总是必须具有相同的类型,不是吗?
之前我曾经使用过python和我的目标" (可能是C ++的错误设置)是获得等效的嵌套python字典。
答案 0 :(得分:9)
是的,您可以创建一个嵌套数据结构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对象。
答案 1 :(得分:6)
看看nlohmann's JSON Repository on GitHub。我发现这是使用JSON最方便的方法。
它的设计就像STL容器一样,使得它的使用非常直观。
答案 2 :(得分:2)
基本上,javascript和C ++在两个不同的原则上工作。 Javascript创建一个“关联数组”或哈希表,它将字符串键(字段名称)与值匹配。 C ++在内存中布局结构,所以前4个字节是一个整数,这是一个年龄,那么也许我们有一个固定的32字节字符串代表“职业”。
因此,javascript将处理诸如“年龄”在一个记录中为18而在另一个记录中为“十九”的事情。 C ++不能。 (但是C ++要快得多)。
因此,如果我们想在C ++中处理JSON,我们必须从头开始构建关联数组。然后我们必须用它们的类型标记值。它是一个整数,一个实数值(可能返回为“double”),boolean,一个字符串?因此,JSON C ++类是相当大的代码块。实际上我们正在做的是在C ++中实现一些javascript引擎。然后,我们将JSON解析器作为字符串传递给JSON,并对其进行标记,并为我们提供从C ++查询JSON的函数。
答案 3 :(得分:1)
读取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
>
答案 4 :(得分:1)
这是另一个更容易读取json文件的可能性:
#include "json/json.h"
std::ifstream file_input("input.json");
Json::Reader reader;
Json::Value root;
reader.parse(file_input, root);
cout << root;
然后您可以获取如下值:
cout << root["key"]
答案 5 :(得分:1)
使用 sudo dnf install jsoncpp-devel
获取图书馆。
将以下文件存储在您的项目文件夹中:
people.json
{
"Anna":
{
"age": 18,
"profession": "student"
},
"Ben":
{
"age" : "nineteen",
"profession": "mechanic"
}
}
main.cpp
#include <iostream>
#include <fstream>
#include <json/json.h>
int main()
{
Json::Value people;
std::ifstream people_file("people.json", std::ifstream::binary);
people_file >> people;
std::cout << people["Anna"] << "\n";
std::cout << people["Anna"]["profession"] << "\n";
}
使用 g++ -ljsoncpp main.cpp
编译。调用 ./a.out
会产生
输出
{
"age" : 18,
"profession" : "student"
}
"student"
答案 6 :(得分:0)
storing peoples like this
{"Anna" : {
"age": 18,
"profession": "student"},
"Ben" : {
"age" : "nineteen",
"profession": "mechanic"}
}
will cause problems, particularly if differents peoples have same name..
rather use array storing objects like this
{
"peoples":[
{
"name":"Anna",
"age": 18,
"profession": "student"
},
{
"name":"Ben",
"age" : "nineteen",
"profession": "mechanic"
}
]
}
like this, you can enumerates objects, or acces objects by numerical index. remember that json is storage structure, not dynamically sorter or indexer. use data stored in json to build indexes as you need and acces data.
答案 7 :(得分:0)
您可以使用c ++ boost :: property_tree :: ptree解析json数据。这是您的json数据的示例。如果您在每个子节点中移动名称,这将更加容易
#include <iostream>
#include <string>
#include <tuple>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
int main () {
namespace pt = boost::property_tree;
pt::ptree loadPtreeRoot;
pt::read_json("example.json", loadPtreeRoot);
std::vector<std::tuple<std::string, std::string, std::string>> people;
pt::ptree temp ;
pt::ptree tage ;
pt::ptree tprofession ;
std::string age ;
std::string profession ;
//Get first child
temp = loadPtreeRoot.get_child("Anna");
tage = temp.get_child("age");
tprofession = temp.get_child("profession");
age = tage.get_value<std::string>();
profession = tprofession.get_value<std::string>();
std::cout << "age: " << age << "\n" << "profession :" << profession << "\n" ;
//push tuple to vector
people.push_back(std::make_tuple("Anna", age, profession));
//Get Second child
temp = loadPtreeRoot.get_child("Ben");
tage = temp.get_child("age");
tprofession = temp.get_child("profession");
age = tage.get_value<std::string>();
profession = tprofession.get_value<std::string>();
std::cout << "age: " << age << "\n" << "profession :" << profession << "\n" ;
//push tuple to vector
people.push_back(std::make_tuple("Ben", age, profession));
for (const auto& tmppeople: people) {
std::cout << "Child[" << std::get<0>(tmppeople) << "] = " << " age : "
<< std::get<1>(tmppeople) << "\n profession : " << std::get<2>(tmppeople) << "\n";
}
}