C++ 用C++读取json文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32205981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading json files in C++
提问by user3515814
I'm trying to read in a JSON file. So far I have focused on using the jsoncpp
library. However, the documentation is quite hard to understand for me. Could anyone explain in lay terms what it does?
我正在尝试读取 JSON 文件。到目前为止,我一直专注于使用该jsoncpp
库。但是,文档对我来说很难理解。任何人都可以通俗地解释它的作用吗?
Say I have a people.json
which looks like this:
说我有一个people.json
看起来像这样的:
{"Anna" : {
"age": 18,
"profession": "student"},
"Ben" : {
"age" : "nineteen",
"profession": "mechanic"}
}
What happens when I read this in? Can I create some sort of data structure people
which I can index by Anna
and Ben
as well as age
and profession
? What would be the data type of people
? I thought it would be something similar to a (nested) map, but map values always have to have the same type, don't they?
当我读到这个时会发生什么?我可以建立某种形式的数据结构people
,我可以指数Anna
和Ben
以及age
和profession
?的数据类型是people
什么?我认为它类似于(嵌套)地图,但地图值始终必须具有相同的类型,不是吗?
I have worked with python before and my "goal" (which may be ill-set for C++) is to obtain the equivalent of a nested python dictionary.
我之前曾使用过 python,我的“目标”(对于 C++ 来说可能是错误的)是获得相当于嵌套 python 字典的东西。
采纳答案by Pooja Nilangekar
Yes you can create a nested data structure
people
which can be indexed byAnna
andBen
. However, you can't index it directly byage
andprofession
(I will get to this part in the code).The data type of
people
is of typeJson::Value
(which is defined in jsoncpp). You are right, it is similar to the nested map, butValue
is a data structure which is defined such that multiple types can be stored and accessed. It is similar to a map with astring
as the key andJson::Value
as the value. It could also be a map between anunsigned int
as key andJson::Value
as the value (In case of json arrays).
是的,您可以创建一个
people
可以由Anna
和索引的嵌套数据结构Ben
。但是,您不能直接通过age
and 对其进行索引profession
(我将在代码中介绍这一部分)。的数据类型
people
是类型Json::Value
(在 jsoncpp 中定义)。你是对的,它类似于嵌套映射,但它Value
是一种数据结构,它被定义为可以存储和访问多种类型。它类似于以 astring
作为键和Json::Value
作为值的映射。它也可以是unsigned int
as 键和Json::Value
作为值之间的映射(如果是 json 数组)。
Here's the 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.
As you can see, you can index the json object only based on the hierarchy of the input data.
如您所见,您只能根据输入数据的层次结构对 json 对象进行索引。
回答by Arsen
Have a look at nlohmann's JSON Repository on GitHub. I have found that it is the most convenient way to work with JSON.
在 GitHub 上查看nlohmann 的 JSON 存储库。我发现这是使用 JSON 最方便的方式。
It is designed to behave just like an STL container, which makes its usage very intuitive.
它的设计行为就像一个 STL 容器,这使得它的使用非常直观。
回答by Malcolm McLean
Essentially javascript and C++ work on two different principles. Javascript creates an "associative array" or hash table, which matches a string key, which is the field name, to a value. C++ lays out structures in memory, so the first 4 bytes are an integer, which is an age, then maybe we have a fixed-wth 32 byte string which represents the "profession".
基本上 javascript 和 C++ 工作在两个不同的原则上。Javascript 创建一个“关联数组”或哈希表,它将字符串键(字段名称)与值匹配。C++ 在内存中布置结构,所以前 4 个字节是一个整数,这是一个年龄,然后也许我们有一个固定的 32 字节字符串代表“职业”。
So javascript will handle things like "age" being 18 in one record and "nineteen" in another. C++ can't. (However C++ is much faster).
因此,javascript 将处理诸如“年龄”在一个记录中为 18 岁而在另一个记录中为“十九岁”之类的问题。C++ 不能。(但是 C++ 快得多)。
So if we want to handle JSON in C++, we have to build the associative array from the ground up. Then we have to tag the values with their types. Is it an integer, a real value (probably return as "double"), boolean, a string? It follows that a JSON C++ class is quite a large chunk of code. Effectively what we are doing is implementing a bit of the javascript engine in C++. We then pass our JSON parser the JSON as a string, and it tokenises it, and gives us functions to query the JSON from C++.
所以如果我们想在 C++ 中处理 JSON,我们必须从头开始构建关联数组。然后我们必须用它们的类型标记这些值。它是整数、实数值(可能返回为“double”)、布尔值还是字符串?因此,JSON C++ 类是相当大的代码块。实际上,我们正在做的是用 C++ 实现一些 javascript 引擎。然后我们将 JSON 作为字符串传递给我们的 JSON 解析器,它对它进行标记,并为我们提供从 C++ 查询 JSON 的函数。
回答by Sandesh Kumar Sodhi
Example (with complete source code) to read a json configuration file:
读取json配置文件的示例(含完整源代码):
https://github.com/sksodhi/CodeNuggets/tree/master/json/config_read
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
>
回答by LaLa
Here is another easier possibility to read in a json file:
这是在 json 文件中读取的另一种更简单的可能性:
#include "json/json.h"
std::ifstream file_input("input.json");
Json::Reader reader;
Json::Value root;
reader.parse(file_input, root);
cout << root;
You can then get the values like this:
然后你可以得到这样的值:
cout << root["key"]
回答by ChauhanTs
You can use c++ boost::property_tree::ptree for parsing json data. here is the example for your json data. this would be more easy if you shift name inside each child nodes
您可以使用 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";
}
}
回答by christian audebert
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.
像这样,您可以枚举对象,或通过数字索引访问对象。请记住,json 是存储结构,而不是动态排序器或索引器。使用存储在 json 中的数据根据需要构建索引并访问数据。